Merge remote-tracking branch 'origin/development' into general-N_constituents

This commit is contained in:
Martin Diehl 2020-10-12 05:27:11 +02:00
commit 72ba4645cb
24 changed files with 832 additions and 627 deletions

1
.gitattributes vendored
View File

@ -8,6 +8,7 @@
*.jpg binary *.jpg binary
*.hdf5 binary *.hdf5 binary
*.pdf binary *.pdf binary
*.dream3d binary
# ignore files from MSC.Marc in language statistics # ignore files from MSC.Marc in language statistics
installation/mods_MarcMentat/20*/* linguist-vendored installation/mods_MarcMentat/20*/* linguist-vendored

View File

@ -193,6 +193,8 @@ grid_mech_compile_Intel:
- module load $IntelCompiler $MPICH_Intel $PETSc_MPICH_Intel - module load $IntelCompiler $MPICH_Intel $PETSc_MPICH_Intel
- cp -r grid_mech_compile grid_mech_compile_Intel - cp -r grid_mech_compile grid_mech_compile_Intel
- grid_mech_compile_Intel/test.py - grid_mech_compile_Intel/test.py
- cd pytest
- pytest -k 'compile and grid'
except: except:
- master - master
- release - release
@ -203,6 +205,8 @@ Compile_FEM_Intel:
- module load $IntelCompiler $MPICH_Intel $PETSc_MPICH_Intel - module load $IntelCompiler $MPICH_Intel $PETSc_MPICH_Intel
- cp -r FEM_compile FEM_compile_Intel - cp -r FEM_compile FEM_compile_Intel
- FEM_compile_Intel/test.py - FEM_compile_Intel/test.py
- cd pytest
- pytest -k 'compile and mesh'
except: except:
- master - master
- release - release
@ -213,6 +217,8 @@ grid_mech_compile_GNU:
- module load $GNUCompiler $MPICH_GNU $PETSc_MPICH_GNU - module load $GNUCompiler $MPICH_GNU $PETSc_MPICH_GNU
- cp -r grid_mech_compile grid_mech_compile_GNU - cp -r grid_mech_compile grid_mech_compile_GNU
- grid_mech_compile_GNU/test.py - grid_mech_compile_GNU/test.py
- cd pytest
- pytest -k 'compile and grid'
except: except:
- master - master
- release - release
@ -223,6 +229,8 @@ Compile_FEM_GNU:
- module load $GNUCompiler $MPICH_GNU $PETSc_MPICH_GNU - module load $GNUCompiler $MPICH_GNU $PETSc_MPICH_GNU
- cp -r FEM_compile FEM_compile_GNU - cp -r FEM_compile FEM_compile_GNU
- FEM_compile_GNU/test.py - FEM_compile_GNU/test.py
- cd pytest
- pytest -k 'compile and mesh'
except: except:
- master - master
- release - release
@ -244,7 +252,7 @@ Pytest_grid:
script: script:
- module load $IntelCompiler $MPICH_Intel $PETSc_MPICH_Intel - module load $IntelCompiler $MPICH_Intel $PETSc_MPICH_Intel
- cd pytest - cd pytest
- pytest - pytest -m 'not compile'
except: except:
- master - master
- release - release
@ -320,6 +328,8 @@ Marc_compileIfort:
script: script:
- module load $IntelMarc $HDF5Marc $MSC - module load $IntelMarc $HDF5Marc $MSC
- Marc_compileIfort/test.py - Marc_compileIfort/test.py
- cd pytest
- pytest -k 'compile and Marc'
except: except:
- master - master
- release - release

View File

@ -1 +1 @@
v3.0.0-alpha-452-gd3f068cd7 v3.0.0-alpha-502-g8ab405e5d

View File

@ -1,3 +1,4 @@
---
homogenization: homogenization:
SX: SX:
N_constituents: 1 N_constituents: 1

View File

@ -1,76 +0,0 @@
#!/usr/bin/env python3
import os
import sys
from io import StringIO
from optparse import OptionParser
from scipy import ndimage
import damask
scriptName = os.path.splitext(os.path.basename(__file__))[0]
scriptID = ' '.join([scriptName,damask.version])
# --------------------------------------------------------------------
# MAIN
# --------------------------------------------------------------------
parser = OptionParser(option_class=damask.extendableOption, usage='%prog option [ASCIItable(s)]', description = """
Add column(s) containing Gaussian filtered values of requested column(s).
Operates on periodic and non-periodic ordered three-dimensional data sets.
For details see scipy.ndimage documentation.
""", version = scriptID)
parser.add_option('-p','--pos','--periodiccellcenter',
dest = 'pos',
type = 'string', metavar = 'string',
help = 'label of coordinates [%default]')
parser.add_option('-s','--scalar',
dest = 'labels',
action = 'extend', metavar = '<string LIST>',
help = 'label(s) of scalar field values')
parser.add_option('-o','--order',
dest = 'order',
type = int,
metavar = 'int',
help = 'order of the filter [%default]')
parser.add_option('--sigma',
dest = 'sigma',
type = float,
metavar = 'float',
help = 'standard deviation [%default]')
parser.add_option('--periodic',
dest = 'periodic',
action = 'store_true',
help = 'assume periodic grain structure')
parser.set_defaults(pos = 'pos',
order = 0,
sigma = 1,
)
(options,filenames) = parser.parse_args()
if filenames == []: filenames = [None]
if options.labels is None: parser.error('no data column specified.')
for name in filenames:
damask.util.report(scriptName,name)
table = damask.Table.load(StringIO(''.join(sys.stdin.read())) if name is None else name)
damask.grid_filters.coord0_check(table.get(options.pos))
for label in options.labels:
table = table.add('Gauss{}({})'.format(options.sigma,label),
ndimage.filters.gaussian_filter(table.get(label).reshape(-1),
options.sigma,options.order,
mode = 'wrap' if options.periodic else 'nearest'),
scriptID+' '+' '.join(sys.argv[1:]))
table.save((sys.stdout if name is None else name), legacy=True)

View File

@ -1,12 +1,8 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import os import os
import sys
from optparse import OptionParser from optparse import OptionParser
import h5py
import numpy as np
import damask import damask
@ -64,88 +60,12 @@ parser.set_defaults(pointwise = 'CellData',
if options.basegroup is None: if options.basegroup is None:
parser.error('No base group selected') parser.error('No base group selected')
rootDir ='DataContainers'
if filenames == []: parser.error('no input file specified.') if filenames == []: parser.error('no input file specified.')
for name in filenames: for name in filenames:
damask.util.report(scriptName,name) damask.util.report(scriptName,name)
errors = [] geom = damask.Geom.load_DREAM3D(name,options.basegroup,options.pointwise)
damask.util.croak(geom)
inFile = h5py.File(name, 'r') geom.save_ASCII(os.path.splitext(name)[0]+'.geom',compress=False)
group_geom = os.path.join(rootDir,options.basegroup,'_SIMPL_GEOMETRY')
try:
size = inFile[os.path.join(group_geom,'DIMENSIONS')][...] \
* inFile[os.path.join(group_geom,'SPACING')][...]
grid = inFile[os.path.join(group_geom,'DIMENSIONS')][...]
origin = inFile[os.path.join(group_geom,'ORIGIN')][...]
except KeyError:
errors.append('Geometry data ({}) not found'.format(group_geom))
group_pointwise = os.path.join(rootDir,options.basegroup,options.pointwise)
if options.average is None:
label = 'Point'
dataset = os.path.join(group_pointwise,options.quaternion)
try:
quats = np.reshape(inFile[dataset][...],(np.product(grid),4))
rot = [damask.Rotation.from_quaternion(q,True,P=+1) for q in quats]
except KeyError:
errors.append('Pointwise orientation (quaternion) data ({}) not readable'.format(dataset))
dataset = os.path.join(group_pointwise,options.phase)
try:
phase = np.reshape(inFile[dataset][...],(np.product(grid)))
except KeyError:
errors.append('Pointwise phase data ({}) not readable'.format(dataset))
microstructure = np.arange(1,np.product(grid)+1,dtype=int).reshape(grid,order='F')
else:
label = 'Grain'
dataset = os.path.join(group_pointwise,options.microstructure)
try:
microstructure = np.transpose(inFile[dataset][...].reshape(grid[::-1]),(2,1,0)) # convert from C ordering
except KeyError:
errors.append('Link between pointwise and grain average data ({}) not readable'.format(dataset))
group_average = os.path.join(rootDir,options.basegroup,options.average)
dataset = os.path.join(group_average,options.quaternion)
try:
rot = [damask.Rotation.from_quaternion(q,True,P=+1) for q in inFile[dataset][...][1:]] # skip first entry (unindexed)
except KeyError:
errors.append('Average orientation data ({}) not readable'.format(dataset))
dataset = os.path.join(group_average,options.phase)
try:
phase = [i[0] for i in inFile[dataset][...]][1:] # skip first entry (unindexed)
except KeyError:
errors.append('Average phase data ({}) not readable'.format(dataset))
if errors != []:
damask.util.croak(errors)
continue
config_header = ['<texture>']
for i in range(np.nanmax(microstructure)):
config_header += ['[{}{}]'.format(label,i+1),
'(gauss)\tphi1 {:.2f}\tPhi {:.2f}\tphi2 {:.2f}'.format(*rot[i].as_Eulers(degrees = True)),
]
config_header += ['<microstructure>']
for i in range(np.nanmax(microstructure)):
config_header += ['[{}{}]'.format(label,i+1),
'(constituent)\tphase {}\ttexture {}\tfraction 1.0'.format(phase[i],i+1),
]
header = [scriptID + ' ' + ' '.join(sys.argv[1:])]\
+ config_header
geom = damask.Geom(microstructure,size,origin,comments=header)
damask.util.croak(geom)
geom.save_ASCII(os.path.splitext(name)[0]+'.geom',compress=False)

View File

@ -2,11 +2,8 @@
import os import os
import sys import sys
from io import StringIO
from optparse import OptionParser from optparse import OptionParser
import numpy as np
import damask import damask
@ -40,64 +37,21 @@ parser.add_option('-q', '--quaternion',
dest = 'quaternion', dest = 'quaternion',
type = 'string', metavar='string', type = 'string', metavar='string',
help = 'quaternion label') help = 'quaternion label')
parser.add_option('--axes',
dest = 'axes',
type = 'string', nargs = 3, metavar = ' '.join(['string']*3),
help = 'orientation coordinate frame in terms of position coordinate frame [+x +y +z]')
parser.set_defaults(pos= 'pos')
parser.set_defaults(pos = 'pos',
)
(options,filenames) = parser.parse_args() (options,filenames) = parser.parse_args()
if filenames == []: filenames = [None] if filenames == []: filenames = [None]
if np.sum([options.quaternion is not None,
options.microstructure is not None]) != 1:
parser.error('need either microstructure or quaternion (and optionally phase) as input.')
if options.microstructure is not None and options.phase is not None:
parser.error('need either microstructure or phase (and mandatory quaternion) as input.')
if options.axes is not None and not set(options.axes).issubset(set(['x','+x','-x','y','+y','-y','z','+z','-z'])):
parser.error('invalid axes {} {} {}.'.format(*options.axes))
for name in filenames: for name in filenames:
damask.util.report(scriptName,name) damask.util.report(scriptName,name)
table = damask.Table.load(StringIO(''.join(sys.stdin.read())) if name is None else name) labels = []
table.sort_by(['{}_{}'.format(i,options.pos) for i in range(3,0,-1)]) # x fast, y slow for l in [options.quaternion,options.phase,options.microstructure]:
grid,size,origin = damask.grid_filters.cell_coord0_gridSizeOrigin(table.get(options.pos)) if l is not None: labels.append(l)
config_header = table.comments t = damask.Table.load(name)
geom = damask.Geom.from_table(t,options.pos,labels)
if options.microstructure:
microstructure = table.get(options.microstructure).reshape(grid,order='F')
elif options.quaternion:
q = table.get(options.quaternion)
phase = table.get(options.phase).astype(int) if options.phase else \
np.ones((table.data.shape[0],1),dtype=int)
unique,unique_inverse = np.unique(np.hstack((q,phase)),return_inverse=True,axis=0)
microstructure = unique_inverse.reshape(grid,order='F') + 1
config_header = ['<texture>']
for i,data in enumerate(unique):
ori = damask.Rotation(data[0:4])
config_header += ['[Grain{}]'.format(i+1),
'(gauss)\tphi1 {:.2f}\tPhi {:.2f}\tphi2 {:.2f}'.format(*ori.as_Eulers(degrees = True)),
]
if options.axes is not None: config_header += ['axes\t{} {} {}'.format(*options.axes)]
config_header += ['<microstructure>']
for i,data in enumerate(unique):
config_header += ['[Grain{}]'.format(i+1),
'(constituent)\tphase {}\ttexture {}\tfraction 1.0'.format(int(data[4]),i+1),
]
header = [scriptID + ' ' + ' '.join(sys.argv[1:])]\
+ config_header
geom = damask.Geom(microstructure,size,origin,
comments=header)
damask.util.croak(geom) damask.util.croak(geom)
geom.save_ASCII(sys.stdout if name is None else os.path.splitext(name)[0]+'.geom',compress=False) geom.save_ASCII(sys.stdout if name is None else os.path.splitext(name)[0]+'.geom',compress=False)

View File

@ -10,20 +10,21 @@ with open(_Path(__file__).parent/_Path('VERSION')) as _f:
# make classes directly accessible as damask.Class # make classes directly accessible as damask.Class
from ._environment import Environment as _ # noqa from ._environment import Environment as _ # noqa
environment = _() environment = _()
from ._table import Table # noqa from . import util # noqa
from ._vtk import VTK # noqa from . import seeds # noqa
from ._colormap import Colormap # noqa from . import mechanics # noqa
from ._rotation import Rotation # noqa from . import solver # noqa
from ._lattice import Symmetry, Lattice# noqa from . import grid_filters # noqa
from ._orientation import Orientation # noqa from ._lattice import Symmetry, Lattice# noqa
from ._result import Result # noqa from ._table import Table # noqa
from ._geom import Geom # noqa from ._rotation import Rotation # noqa
from ._material import Material # noqa from ._vtk import VTK # noqa
from . import solver # noqa from ._colormap import Colormap # noqa
from . import util # noqa from ._orientation import Orientation # noqa
from . import seeds # noqa from ._config import Config # noqa
from . import grid_filters # noqa from ._configmaterial import ConfigMaterial # noqa
from . import mechanics # noqa from ._geom import Geom # noqa
from ._result import Result # noqa

80
python/damask/_config.py Normal file
View File

@ -0,0 +1,80 @@
from io import StringIO
import abc
import yaml
class NiceDumper(yaml.SafeDumper):
"""Make YAML readable for humans."""
def write_line_break(self, data=None):
super().write_line_break(data)
if len(self.indents) == 1:
super().write_line_break()
def increase_indent(self, flow=False, indentless=False):
return super().increase_indent(flow, False)
class Config(dict):
"""YAML-based configuration."""
def __repr__(self):
"""Show as in file."""
output = StringIO()
self.save(output)
output.seek(0)
return ''.join(output.readlines())
@classmethod
def load(cls,fname):
"""
Load from yaml file.
Parameters
----------
fname : file, str, or pathlib.Path
Filename or file for writing.
"""
try:
fhandle = open(fname)
except TypeError:
fhandle = fname
return cls(yaml.safe_load(fhandle))
def save(self,fname,**kwargs):
"""
Save to yaml file.
Parameters
----------
fname : file, str, or pathlib.Path
Filename or file for writing.
**kwargs : dict
Keyword arguments parsed to yaml.dump.
"""
try:
fhandle = open(fname,'w')
except TypeError:
fhandle = fname
if 'width' not in kwargs:
kwargs['width'] = 256
if 'default_flow_style' not in kwargs:
kwargs['default_flow_style'] = None
fhandle.write(yaml.dump(dict(self),Dumper=NiceDumper,**kwargs))
@property
@abc.abstractmethod
def is_complete(self):
"""Check for completeness."""
pass
@property
@abc.abstractmethod
def is_valid(self):
"""Check for valid file layout."""
pass

View File

@ -0,0 +1,299 @@
import copy
import numpy as np
from . import grid_filters
from . import Config
from . import Lattice
from . import Rotation
class ConfigMaterial(Config):
"""Material configuration."""
def save(self,fname='material.yaml',**kwargs):
"""
Save to yaml file.
Parameters
----------
fname : file, str, or pathlib.Path, optional
Filename or file for writing. Defaults to 'material.yaml'.
**kwargs
Keyword arguments parsed to yaml.dump.
"""
super().save(fname,**kwargs)
@staticmethod
def from_table(table,coordinates=None,constituents={},**kwargs):
"""
Load from an ASCII table.
Parameters
----------
table : damask.Table
Table that contains material information.
coordinates : str, optional
Label of spatial coordiates. Used for sorting and performing a
sanity check. Default to None, in which case no sorting or checking is
peformed.
constituents : dict, optional
Entries for 'constituents'. The key is the name and the value specifies
the label of the data column in the table
**kwargs
Keyword arguments where the key is the name and the value specifies
the label of the data column in the table
Examples
--------
>>> import damask
>>> import damask.ConfigMaterial as cm
>>> t = damask.Table.load('small.txt')
>>> t
pos pos pos qu qu qu qu phase homog
0 0 0 0 0.19 0.8 0.24 -0.51 Aluminum SX
1 1 0 0 0.8 0.19 0.24 -0.51 Steel SX
>>> cm.from_table(t,'pos',{'O':'qu','phase':'phase'},homogenization='homog')
material:
- constituents:
- O: [0.19, 0.8, 0.24, -0.51]
fraction: 1.0
phase: Aluminum
homogenization: SX
- constituents:
- O: [0.8, 0.19, 0.24, -0.51]
fraction: 1.0
phase: Steel
homogenization: SX
"""
if coordinates is not None:
t = table.sort_by([f'{i}_{coordinates}' for i in range(3,0,-1)])
grid_filters.coord0_check(t.get(coordinates))
else:
t = table
constituents_ = {k:t.get(v) for k,v in constituents.items()}
kwargs_ = {k:t.get(v) for k,v in kwargs.items()}
_,idx = np.unique(np.hstack(list({**constituents_,**kwargs_}.values())),return_index=True,axis=0)
constituents_ = {k:v[idx].squeeze() for k,v in constituents_.items()}
kwargs_ = {k:v[idx].squeeze() for k,v in kwargs_.items()}
return ConfigMaterial().material_add(constituents_,**kwargs_)
@property
def is_complete(self):
"""Check for completeness."""
ok = True
for top_level in ['homogenization','phase','material']:
# ToDo: With python 3.8 as prerequisite we can shorten with :=
ok &= top_level in self
if top_level not in self: print(f'{top_level} entry missing')
if ok:
ok &= len(self['material']) > 0
if len(self['material']) < 1: print('Incomplete material definition')
if ok:
homogenization = set()
phase = set()
for i,v in enumerate(self['material']):
if 'homogenization' in v:
homogenization.add(v['homogenization'])
else:
print(f'No homogenization specified in material {i}')
ok = False
if 'constituents' in v:
for ii,vv in enumerate(v['constituents']):
if 'O' not in vv:
print('No orientation specified in constituent {ii} of material {i}')
ok = False
if 'phase' in vv:
phase.add(vv['phase'])
else:
print(f'No phase specified in constituent {ii} of material {i}')
ok = False
for k,v in self['phase'].items():
if 'lattice' not in v:
print(f'No lattice specified in phase {k}')
ok = False
for k,v in self['homogenization'].items():
if 'N_constituents' not in v:
print(f'No. of constituents not specified in homogenization {k}')
ok = False
if phase - set(self['phase']):
print(f'Phase(s) {phase-set(self["phase"])} missing')
ok = False
if homogenization - set(self['homogenization']):
print(f'Homogenization(s) {homogenization-set(self["homogenization"])} missing')
ok = False
return ok
@property
def is_valid(self):
"""Check for valid file layout."""
ok = True
if 'phase' in self:
for k,v in self['phase'].items():
if 'lattice' in v:
try:
Lattice(v['lattice'])
except KeyError:
s = v['lattice']
print(f"Invalid lattice: '{s}' in phase '{k}'")
ok = False
if 'material' in self:
for i,v in enumerate(self['material']):
if 'constituents' in v:
f = 0.0
for c in v['constituents']:
f+= float(c['fraction'])
if 'O' in c:
try:
Rotation.from_quaternion(c['O'])
except ValueError:
o = c['O']
print(f"Invalid orientation: '{o}' in material '{i}'")
ok = False
if not np.isclose(f,1.0):
print(f"Invalid total fraction '{f}' in material '{i}'")
ok = False
return ok
def material_rename_phase(self,mapping,ID=None,constituent=None):
"""
Change phase name in material.
Parameters
----------
mapping: dictionary
Mapping from old name to new name
ID: list of ints, optional
Limit renaming to selected material IDs.
constituent: list of ints, optional
Limit renaming to selected constituents.
"""
dup = copy.deepcopy(self)
for i,m in enumerate(dup['material']):
if ID and i not in ID: continue
for c in m['constituents']:
if constituent is not None and c not in constituent: continue
try:
c['phase'] = mapping[c['phase']]
except KeyError:
continue
return dup
def material_rename_homogenization(self,mapping,ID=None):
"""
Change homogenization name in material.
Parameters
----------
mapping: dictionary
Mapping from old name to new name
ID: list of ints, optional
Limit renaming to selected homogenization IDs.
"""
dup = copy.deepcopy(self)
for i,m in enumerate(dup['material']):
if ID and i not in ID: continue
try:
m['homogenization'] = mapping[m['homogenization']]
except KeyError:
continue
return dup
def material_add(self,constituents,**kwargs):
"""
Add material entries.
Parameters
----------
constituents : dict
Entries for 'constituents'. The key is the name and the value specifies
the label of the data column in the table
**kwargs
Keyword arguments where the key is the name and the value specifies
the label of the data column in the table
Examples
--------
>>> import damask
>>> m = damask.ConfigMaterial()
>>> O = damask.Rotation.from_random(3).as_quaternion()
>>> phase = ['Aluminum','Steel','Aluminum']
>>> m.material_add(constituents={'phase':phase,'O':O},homogenization='SX')
material:
- constituents:
- O: [0.577764, -0.146299, -0.617669, 0.513010]
fraction: 1.0
phase: Aluminum
homogenization: SX
- constituents:
- O: [0.184176, 0.340305, 0.737247, 0.553840]
fraction: 1.0
phase: Steel
homogenization: SX
- constituents:
- O: [0.0886257, -0.144848, 0.615674, -0.769487]
fraction: 1.0
phase: Aluminum
homogenization: SX
"""
c = [{'constituents':u} for u in ConfigMaterial._constituents(**constituents)]
for k,v in kwargs.items():
if hasattr(v,'__len__') and not isinstance(v,str):
if len(v) != len(c):
raise ValueError('len mismatch 1')
for i,vv in enumerate(v):
c[i][k] = [w.item() for w in vv] if isinstance(vv,np.ndarray) else vv.item()
else:
for i in range(len(c)):
c[i][k] = v
dup = copy.deepcopy(self)
if 'material' not in dup: dup['material'] = []
dup['material'] +=c
return dup
@staticmethod
def _constituents(N=1,**kwargs):
"""Construct list of constituents."""
for v in kwargs.values():
if hasattr(v,'__len__') and not isinstance(v,str): N_material = len(v)
if N == 1:
m = [[{'fraction':1.0}] for _ in range(N_material)]
for k,v in kwargs.items():
if hasattr(v,'__len__') and not isinstance(v,str):
if len(v) != N_material:
raise ValueError('len mismatch 2')
for i,vv in enumerate(np.array(v)):
m[i][0][k] = [w.item() for w in vv] if isinstance(vv,np.ndarray) else vv.item()
else:
for i in range(N_material):
m[i][0][k] = v
return m
else:
raise NotImplementedError

View File

@ -1,15 +1,17 @@
import copy import copy
import multiprocessing as mp import multiprocessing as mp
from functools import partial from functools import partial
from os import path
import numpy as np import numpy as np
import h5py
from scipy import ndimage,spatial from scipy import ndimage,spatial
from . import environment from . import environment
from . import Rotation
from . import VTK from . import VTK
from . import util from . import util
from . import grid_filters from . import grid_filters
from . import Rotation
class Geom: class Geom:
@ -207,6 +209,68 @@ class Geom:
return Geom(material.reshape(grid,order='F'),size,origin,comments) return Geom(material.reshape(grid,order='F'),size,origin,comments)
@staticmethod
def load_DREAM3D(fname,base_group,point_data=None,material='FeatureIds'):
"""
Load a DREAM.3D file.
Parameters
----------
fname : str
Filename of the DREAM.3D file
base_group : str
Name of the group (folder) below 'DataContainers'. For example
'SyntheticVolumeDataContainer'.
point_data : str, optional
Name of the group (folder) containing the point wise material data,
for example 'CellData'. Defaults to None, in which case points consecutively numbered.
material : str, optional
Name of the dataset containing the material ID. Defaults to
'FeatureIds'.
"""
root_dir ='DataContainers'
f = h5py.File(fname, 'r')
g = path.join(root_dir,base_group,'_SIMPL_GEOMETRY')
size = f[path.join(g,'DIMENSIONS')][()] * f[path.join(g,'SPACING')][()]
grid = f[path.join(g,'DIMENSIONS')][()]
origin = f[path.join(g,'ORIGIN')][()]
group_pointwise = path.join(root_dir,base_group,point_data)
ma = np.arange(1,np.product(grid)+1,dtype=int) if point_data is None else \
np.reshape(f[path.join(group_pointwise,material)],grid.prod())
return Geom(ma.reshape(grid,order='F'),size,origin,util.execution_stamp('Geom','load_DREAM3D'))
@staticmethod
def from_table(table,coordinates,labels):
"""
Load an ASCII table.
Parameters
----------
table : damask.Table
Table that contains material information.
coordinates : str
Label of the column containing the spatial coordinates.
labels : str or list of str
Label(s) of the columns containing the material definition.
Each unique combintation of values results in a material.
"""
t = table.sort_by([f'{i}_{coordinates}' for i in range(3,0,-1)])
grid,size,origin = grid_filters.cell_coord0_gridSizeOrigin(t.get(coordinates))
labels_ = [labels] if isinstance(labels,str) else labels
_,unique_inverse = np.unique(np.hstack([t.get(l) for l in labels_]),return_inverse=True,axis=0)
ma = unique_inverse.reshape(grid,order='F') + 1
return Geom(ma,size,origin,util.execution_stamp('Geom','from_table'))
@staticmethod @staticmethod
def _find_closest_seed(seeds, weights, point): def _find_closest_seed(seeds, weights, point):
return np.argmin(np.sum((np.broadcast_to(point,(len(seeds),3))-seeds)**2,axis=1) - weights) return np.argmin(np.sum((np.broadcast_to(point,(len(seeds),3))-seeds)**2,axis=1) - weights)
@ -353,7 +417,7 @@ class Geom:
Number of periods per unit cell. Defaults to 1. Number of periods per unit cell. Defaults to 1.
materials : (int, int), optional materials : (int, int), optional
Material IDs. Defaults to (1,2). Material IDs. Defaults to (1,2).
Notes Notes
----- -----
The following triply-periodic minimal surfaces are implemented: The following triply-periodic minimal surfaces are implemented:
@ -399,7 +463,7 @@ class Geom:
def save(self,fname,compress=True): def save(self,fname,compress=True):
""" """
Generates vtk rectilinear grid. Store as vtk rectilinear grid.
Parameters Parameters
---------- ----------
@ -536,7 +600,7 @@ class Geom:
coords_rot = R.broadcast_to(tuple(self.grid))@coords coords_rot = R.broadcast_to(tuple(self.grid))@coords
with np.errstate(all='ignore'): with np.errstate(all='ignore'):
mask = np.where(np.sum(np.power(coords_rot/r,2.0**exponent),axis=-1) > 1.0,True,False) mask = np.sum(np.power(coords_rot/r,2.0**np.array(exponent)),axis=-1) > 1.0
if periodic: # translate back to center if periodic: # translate back to center
mask = np.roll(mask,((c-np.ones(3)*.5)*self.grid).astype(int),(0,1,2)) mask = np.roll(mask,((c-np.ones(3)*.5)*self.grid).astype(int),(0,1,2))

View File

@ -1,193 +0,0 @@
from io import StringIO
import copy
import yaml
import numpy as np
from . import Lattice
from . import Rotation
class NiceDumper(yaml.SafeDumper):
"""Make YAML readable for humans."""
def write_line_break(self, data=None):
super().write_line_break(data)
if len(self.indents) == 1:
super().write_line_break()
def increase_indent(self, flow=False, indentless=False):
return super().increase_indent(flow, False)
class Material(dict):
"""Material configuration."""
def __repr__(self):
"""Show as in file."""
output = StringIO()
self.save(output)
output.seek(0)
return ''.join(output.readlines())
@staticmethod
def load(fname):
"""Load from yaml file."""
try:
fhandle = open(fname)
except TypeError:
fhandle = fname
return Material(yaml.safe_load(fhandle))
def save(self,fname='material.yaml'):
"""
Save to yaml file.
Parameters
----------
fname : file, str, or pathlib.Path
Filename or file for reading.
"""
try:
fhandle = open(fname,'w')
except TypeError:
fhandle = fname
fhandle.write(yaml.dump(dict(self),width=256,default_flow_style=None,Dumper=NiceDumper))
@property
def is_complete(self):
"""Check for completeness."""
ok = True
for top_level in ['homogenization','phase','microstructure']:
# ToDo: With python 3.8 as prerequisite we can shorten with :=
ok &= top_level in self
if top_level not in self: print(f'{top_level} entry missing')
if ok:
ok &= len(self['microstructure']) > 0
if len(self['microstructure']) < 1: print('Incomplete microstructure definition')
if ok:
homogenization = set()
phase = set()
for i,v in enumerate(self['microstructure']):
if 'homogenization' in v:
homogenization.add(v['homogenization'])
else:
print(f'No homogenization specified in microstructure {i}')
ok = False
if 'constituents' in v:
for ii,vv in enumerate(v['constituents']):
if 'orientation' not in vv:
print('No orientation specified in constituent {ii} of microstructure {i}')
ok = False
if 'phase' in vv:
phase.add(vv['phase'])
else:
print(f'No phase specified in constituent {ii} of microstructure {i}')
ok = False
for k,v in self['phase'].items():
if 'lattice' not in v:
print(f'No lattice specified in phase {k}')
ok = False
#for k,v in self['homogenization'].items():
# if 'N_constituents' not in v:
# print(f'No. of constituents not specified in homogenization {k}'}
# ok = False
if phase - set(self['phase']):
print(f'Phase(s) {phase-set(self["phase"])} missing')
ok = False
if homogenization - set(self['homogenization']):
print(f'Homogenization(s) {homogenization-set(self["homogenization"])} missing')
ok = False
return ok
@property
def is_valid(self):
"""Check for valid file layout."""
ok = True
if 'phase' in self:
for k,v in self['phase'].items():
if 'lattice' in v:
try:
Lattice(v['lattice'])
except KeyError:
s = v['lattice']
print(f"Invalid lattice: '{s}' in phase '{k}'")
ok = False
if 'microstructure' in self:
for i,v in enumerate(self['microstructure']):
if 'constituents' in v:
f = 0.0
for c in v['constituents']:
f+= float(c['fraction'])
if 'orientation' in c:
try:
Rotation.from_quaternion(c['orientation'])
except ValueError:
o = c['orientation']
print(f"Invalid orientation: '{o}' in microstructure '{i}'")
ok = False
if not np.isclose(f,1.0):
print(f"Invalid total fraction '{f}' in microstructure '{i}'")
ok = False
return ok
def microstructure_rename_phase(self,mapping,ID=None,constituent=None):
"""
Change phase name in microstructure.
Parameters
----------
mapping: dictionary
Mapping from old name to new name
ID: list of ints, optional
Limit renaming to selected microstructure IDs.
constituent: list of ints, optional
Limit renaming to selected constituents.
"""
dup = copy.deepcopy(self)
for i,m in enumerate(dup['microstructure']):
if ID and i not in ID: continue
for c in m['constituents']:
if constituent is not None and c not in constituent: continue
try:
c['phase'] = mapping[c['phase']]
except KeyError:
continue
return dup
def microstructure_rename_homogenization(self,mapping,ID=None):
"""
Change homogenization name in microstructure.
Parameters
----------
mapping: dictionary
Mapping from old name to new name
ID: list of ints, optional
Limit renaming to selected homogenization IDs.
"""
dup = copy.deepcopy(self)
for i,m in enumerate(dup['microstructure']):
if ID and i not in ID: continue
try:
m['homogenization'] = mapping[m['homogenization']]
except KeyError:
continue
return dup

View File

@ -33,6 +33,10 @@ class Table:
"""Brief overview.""" """Brief overview."""
return util.srepr(self.comments)+'\n'+self.data.__repr__() return util.srepr(self.comments)+'\n'+self.data.__repr__()
def __len__(self):
"""Number of rows."""
return len(self.data)
def __copy__(self): def __copy__(self):
"""Copy Table.""" """Copy Table."""
return copy.deepcopy(self) return copy.deepcopy(self)

View File

@ -1,33 +1,35 @@
homogenization: homogenization:
SX: SX:
N_constituents: 2
mech: {type: none} mech: {type: none}
Taylor: Taylor:
mech: {type: isostrain, N_constituents: 2} N_constituents: 2
mech: {type: isostrain}
microstructure: material:
- constituents: - constituents:
- fraction: 1.0 - fraction: 1.0
orientation: [1.0, 0.0, 0.0, 0.0] O: [1.0, 0.0, 0.0, 0.0]
phase: Aluminum phase: Aluminum
homogenization: SX homogenization: SX
- constituents: - constituents:
- fraction: 1.0 - fraction: 1.0
orientation: [0.7936696712125002, -0.28765777461664166, -0.3436487135089419, 0.4113964260949434] O: [0.7936696712125002, -0.28765777461664166, -0.3436487135089419, 0.4113964260949434]
phase: Aluminum phase: Aluminum
homogenization: SX homogenization: SX
- constituents: - constituents:
- fraction: 1.0 - fraction: 1.0
orientation: [0.3986143167493579, -0.7014883552495493, 0.2154871765709027, 0.5500781677772945] O: [0.3986143167493579, -0.7014883552495493, 0.2154871765709027, 0.5500781677772945]
phase: Aluminum phase: Aluminum
homogenization: SX homogenization: SX
- homogenization: Taylor - constituents:
constituents: - fraction: 0.5
- fraction: .5 O: [0.28645844315788244, -0.022571491243423537, -0.467933059311115, -0.8357456192708106]
orientation: [0.28645844315788244, -0.022571491243423537, -0.467933059311115, -0.8357456192708106]
phase: Aluminum phase: Aluminum
- fraction: .5 - fraction: 0.5
orientation: [0.3986143167493579, -0.7014883552495493, 0.2154871765709027, 0.5500781677772945] O: [0.3986143167493579, -0.7014883552495493, 0.2154871765709027, 0.5500781677772945]
phase: Steel phase: Steel
homogenization: Taylor
phase: phase:
Aluminum: Aluminum:

View File

@ -0,0 +1,37 @@
import pytest
from damask import Config
class TestConfig:
@pytest.mark.parametrize('flow_style',[None,True,False])
def test_load_save_str(self,tmp_path,flow_style):
config = Config()
config['A'] = 1
config['B'] = [2,3]
config.save(tmp_path/'config.yaml',default_flow_style=flow_style)
assert Config.load(tmp_path/'config.yaml') == config
def test_load_save_file(self,tmp_path):
config = Config()
config['A'] = 1
config['B'] = [2,3]
with open(tmp_path/'config.yaml','w') as f:
config.save(f)
with open(tmp_path/'config.yaml') as f:
assert Config.load(f) == config
def test_repr(self,tmp_path):
config = Config()
config['A'] = 1
config['B'] = [2,3]
with open(tmp_path/'config.yaml','w') as f:
f.write(config.__repr__())
assert Config.load(tmp_path/'config.yaml') == config
def test_abstract_is_valid(self):
assert Config().is_valid is None
def test_abstract_is_complete(self):
assert Config().is_complete is None

View File

@ -0,0 +1,76 @@
import os
import pytest
from damask import ConfigMaterial
@pytest.fixture
def reference_dir(reference_dir_base):
"""Directory containing reference results."""
return reference_dir_base/'ConfigMaterial'
class TestConfigMaterial:
@pytest.mark.parametrize('fname',[None,'test.yaml'])
def test_load_save(self,reference_dir,tmp_path,fname):
reference = ConfigMaterial.load(reference_dir/'material.yaml')
os.chdir(tmp_path)
if fname is None:
reference.save()
new = ConfigMaterial.load('material.yaml')
else:
reference.save(fname)
new = ConfigMaterial.load(fname)
assert reference == new
def test_valid_complete(self,reference_dir):
material_config = ConfigMaterial.load(reference_dir/'material.yaml')
assert material_config.is_valid and material_config.is_complete
def test_invalid_lattice(self,reference_dir):
material_config = ConfigMaterial.load(reference_dir/'material.yaml')
material_config['phase']['Aluminum']['lattice']='fxc'
assert not material_config.is_valid
def test_invalid_orientation(self,reference_dir):
material_config = ConfigMaterial.load(reference_dir/'material.yaml')
material_config['material'][0]['constituents'][0]['O']=[0,0,0,0]
assert not material_config.is_valid
def test_invalid_fraction(self,reference_dir):
material_config = ConfigMaterial.load(reference_dir/'material.yaml')
material_config['material'][0]['constituents'][0]['fraction']=.9
assert not material_config.is_valid
@pytest.mark.parametrize('item',['homogenization','phase','material'])
def test_incomplete_missing(self,reference_dir,item):
material_config = ConfigMaterial.load(reference_dir/'material.yaml')
del material_config[item]
assert not material_config.is_complete
@pytest.mark.parametrize('item',['O','phase'])
def test_incomplete_material_constituent(self,reference_dir,item):
material_config = ConfigMaterial.load(reference_dir/'material.yaml')
del material_config['material'][0]['constituents'][0][item]
assert not material_config.is_complete
def test_incomplete_material_homogenization(self,reference_dir):
material_config = ConfigMaterial.load(reference_dir/'material.yaml')
del material_config['material'][0]['homogenization']
assert not material_config.is_complete
def test_incomplete_phase_lattice(self,reference_dir):
material_config = ConfigMaterial.load(reference_dir/'material.yaml')
del material_config['phase']['Aluminum']['lattice']
assert not material_config.is_complete
def test_incomplete_wrong_phase(self,reference_dir):
material_config = ConfigMaterial.load(reference_dir/'material.yaml')
new = material_config.material_rename_phase({'Steel':'FeNbC'})
assert not new.is_complete
def test_incomplete_wrong_homogenization(self,reference_dir):
material_config = ConfigMaterial.load(reference_dir/'material.yaml')
new = material_config.material_rename_homogenization({'Taylor':'isostrain'})
assert not new.is_complete

View File

@ -1,61 +0,0 @@
import os
import pytest
from damask import Material
@pytest.fixture
def reference_dir(reference_dir_base):
"""Directory containing reference results."""
return reference_dir_base/'Material'
class TestMaterial:
@pytest.mark.parametrize('fname',[None,'test.yaml'])
def test_load_save(self,reference_dir,tmp_path,fname):
reference = Material.load(reference_dir/'material.yaml')
os.chdir(tmp_path)
if fname is None:
reference.save()
new = Material.load('material.yaml')
else:
reference.save(fname)
new = Material.load(fname)
assert reference == new
def test_valid_complete(self,reference_dir):
material_config = Material.load(reference_dir/'material.yaml')
assert material_config.is_valid and material_config.is_complete
def test_invalid_lattice(self,reference_dir):
material_config = Material.load(reference_dir/'material.yaml')
material_config['phase']['Aluminum']['lattice']='fxc'
assert not material_config.is_valid
def test_invalid_orientation(self,reference_dir):
material_config = Material.load(reference_dir/'material.yaml')
material_config['microstructure'][0]['constituents'][0]['orientation']=[0,0,0,0]
assert not material_config.is_valid
def test_invalid_fraction(self,reference_dir):
material_config = Material.load(reference_dir/'material.yaml')
material_config['microstructure'][0]['constituents'][0]['fraction']=.9
assert not material_config.is_valid
@pytest.mark.parametrize('item',['homogenization','phase','microstructure'])
def test_incomplete_missing(self,reference_dir,item):
material_config = Material.load(reference_dir/'material.yaml')
del material_config[item]
assert not material_config.is_complete
def test_incomplete_wrong_phase(self,reference_dir):
material_config = Material.load(reference_dir/'material.yaml')
new = material_config.microstructure_rename_phase({'Steel':'FeNbC'})
assert not new.is_complete
def test_incomplete_wrong_homogenization(self,reference_dir):
material_config = Material.load(reference_dir/'material.yaml')
new = material_config.microstructure_rename_homogenization({'Taylor':'isostrain'})
assert not new.is_complete

View File

@ -220,13 +220,26 @@ logical function isKey(line)
if(len(IO_rmComment(line)) == 0) then if(len(IO_rmComment(line)) == 0) then
isKey = .false. isKey = .false.
else else
isKey = IO_rmComment(line(len(IO_rmComment(line)):len(IO_rmComment(line)))) == ':' & isKey = index(IO_rmComment(line),':',back=.false.) == len(IO_rmComment(line)) .and. &
.and. .not. isFlow(line) index(IO_rmComment(line),':',back=.true.) == len(IO_rmComment(line)) .and. &
.not. isFlow(line)
endif endif
end function isKey end function isKey
!--------------------------------------------------------------------------------------------------
! @brief check whether a string is a list in flow style
!--------------------------------------------------------------------------------------------------
logical function isFlowList(line)
character(len=*), intent(in) :: line
isFlowList = index(adjustl(line),'[') == 1
end function isFlowList
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! @brief skip empty lines ! @brief skip empty lines
! @details update start position in the block by skipping empty lines if present. ! @details update start position in the block by skipping empty lines if present.
@ -244,7 +257,6 @@ subroutine skip_empty_lines(blck,s_blck)
if(empty) s_blck = s_blck + index(blck(s_blck:),IO_EOL) if(empty) s_blck = s_blck + index(blck(s_blck:),IO_EOL)
enddo enddo
end subroutine skip_empty_lines end subroutine skip_empty_lines
@ -273,6 +285,58 @@ subroutine skip_file_header(blck,s_blck)
end subroutine skip_file_header end subroutine skip_file_header
!--------------------------------------------------------------------------------------------------
!> @brief check if a line in flow YAML starts and ends in the same line
!--------------------------------------------------------------------------------------------------
logical function flow_is_closed(str,e_char)
character(len=*), intent(in) :: str
character, intent(in) :: e_char !< end of list/dict ( '}' or ']')
integer :: N_sq, & !< number of open square brackets
N_cu, & !< number of open curly brackets
i
character(len=:), allocatable:: line
flow_is_closed = .false.
N_sq = 0
N_cu = 0
if(e_char == ']') line = str(index(str(:),'[')+1:)
if(e_char == '}') line = str(index(str(:),'{')+1:)
do i = 1, len_trim(line)
flow_is_closed = (N_sq==0 .and. N_cu==0 .and. scan(line(i:i),e_char) == 1)
N_sq = N_sq + merge(1,0,line(i:i) == '[')
N_cu = N_cu + merge(1,0,line(i:i) == '{')
N_sq = N_sq - merge(1,0,line(i:i) == ']')
N_cu = N_cu - merge(1,0,line(i:i) == '}')
enddo
end function flow_is_closed
!--------------------------------------------------------------------------------------------------
!> @brief return the flow YAML line without line break
!--------------------------------------------------------------------------------------------------
subroutine remove_line_break(blck,s_blck,e_char,flow_line)
character(len=*), intent(in) :: blck !< YAML in mixed style
integer, intent(inout) :: s_blck
character, intent(in) :: e_char !< end of list/dict ( '}' or ']')
character(len=:), allocatable, intent(out) :: flow_line
logical :: line_end
line_end =.false.
flow_line = ''
do while(.not.line_end)
flow_line = flow_line//IO_rmComment(blck(s_blck:s_blck + index(blck(s_blck:),IO_EOL) - 2))//' '
line_end = flow_is_closed(flow_line,e_char)
s_blck = s_blck + index(blck(s_blck:),IO_EOL)
enddo
end subroutine remove_line_break
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! @brief reads a line of YAML block which is already in flow style ! @brief reads a line of YAML block which is already in flow style
! @details Dicts should be enlcosed within '{}' for it to be consistent with DAMASK YAML parser ! @details Dicts should be enlcosed within '{}' for it to be consistent with DAMASK YAML parser
@ -402,7 +466,7 @@ recursive subroutine lst(blck,flow,s_blck,s_flow,offset)
integer, intent(inout) :: s_blck, & !< start position in blck integer, intent(inout) :: s_blck, & !< start position in blck
s_flow, & !< start position in flow s_flow, & !< start position in flow
offset !< stores leading '- ' in nested lists offset !< stores leading '- ' in nested lists
character(len=:), allocatable :: line character(len=:), allocatable :: line,flow_line
integer :: e_blck,indent integer :: e_blck,indent
indent = indentDepth(blck(s_blck:),offset) indent = indentDepth(blck(s_blck:),offset)
@ -437,8 +501,12 @@ recursive subroutine lst(blck,flow,s_blck,s_flow,offset)
s_blck = e_blck +2 s_blck = e_blck +2
offset = 0 offset = 0
elseif(isFlow(line)) then elseif(isFlow(line)) then
call line_isFlow(flow,s_flow,line) if(isFlowList(line)) then
s_blck = e_blck +2 call remove_line_break(blck,s_blck,']',flow_line)
else
call remove_line_break(blck,s_blck,'}',flow_line)
endif
call line_isFlow(flow,s_flow,flow_line)
offset = 0 offset = 0
endif endif
else ! list item in the same line else ! list item in the same line
@ -448,8 +516,13 @@ recursive subroutine lst(blck,flow,s_blck,s_flow,offset)
s_blck = e_blck +2 s_blck = e_blck +2
offset = 0 offset = 0
elseif(isFlow(line)) then elseif(isFlow(line)) then
call line_isFlow(flow,s_flow,line) s_blck = s_blck + index(blck(s_blck:),'-')
s_blck = e_blck +2 if(isFlowList(line)) then
call remove_line_break(blck,s_blck,']',flow_line)
else
call remove_line_break(blck,s_blck,'}',flow_line)
endif
call line_isFlow(flow,s_flow,flow_line)
offset = 0 offset = 0
else ! non scalar list item else ! non scalar list item
offset = offset + indentDepth(blck(s_blck:))+1 ! offset in spaces to be ignored offset = offset + indentDepth(blck(s_blck:))+1 ! offset in spaces to be ignored
@ -486,8 +559,8 @@ recursive subroutine dct(blck,flow,s_blck,s_flow,offset)
s_flow, & !< start position in flow s_flow, & !< start position in flow
offset offset
character(len=:), allocatable :: line character(len=:), allocatable :: line,flow_line
integer :: e_blck,indent integer :: e_blck,indent,col_pos
logical :: previous_isKey logical :: previous_isKey
previous_isKey = .false. previous_isKey = .false.
@ -521,12 +594,22 @@ recursive subroutine dct(blck,flow,s_blck,s_flow,offset)
endif endif
if(isKeyValue(line)) then if(isKeyValue(line)) then
call keyValue_toFlow(flow,s_flow,line) col_pos = index(line,':')
if(isFlow(line(col_pos+1:))) then
if(isFlowList(line(col_pos+1:))) then
call remove_line_break(blck,s_blck,']',flow_line)
else
call remove_line_break(blck,s_blck,'}',flow_line)
endif
call keyValue_toFlow(flow,s_flow,flow_line)
else
call keyValue_toFlow(flow,s_flow,line)
s_blck = e_blck + 2
endif
else else
call line_toFlow(flow,s_flow,line) call line_toFlow(flow,s_flow,line)
s_blck = e_blck + 2
endif endif
s_blck = e_blck +2
end if end if
if(isScalar(line) .or. isKeyValue(line)) then if(isScalar(line) .or. isKeyValue(line)) then
@ -559,7 +642,7 @@ recursive subroutine decide(blck,flow,s_blck,s_flow,offset)
s_flow, & !< start position in flow s_flow, & !< start position in flow
offset offset
integer :: e_blck integer :: e_blck
character(len=:), allocatable :: line character(len=:), allocatable :: line,flow_line
if(s_blck <= len(blck)) then if(s_blck <= len(blck)) then
call skip_empty_lines(blck,s_blck) call skip_empty_lines(blck,s_blck)
@ -583,8 +666,12 @@ recursive subroutine decide(blck,flow,s_blck,s_flow,offset)
flow(s_flow:s_flow) = '}' flow(s_flow:s_flow) = '}'
s_flow = s_flow + 1 s_flow = s_flow + 1
elseif(isFlow(line)) then elseif(isFlow(line)) then
if(isFlowList(line)) then
call remove_line_break(blck,s_blck,']',flow_line)
else
call remove_line_break(blck,s_blck,'}',flow_line)
endif
call line_isFlow(flow,s_flow,line) call line_isFlow(flow,s_flow,line)
s_blck = e_blck +2
else else
line = line(indentDepth(line)+1:) line = line(indentDepth(line)+1:)
call line_toFlow(flow,s_flow,line) call line_toFlow(flow,s_flow,line)
@ -723,6 +810,36 @@ subroutine selfTest
if (.not. to_flow(flow_mixed_braces) == flow) error stop 'to_flow' if (.not. to_flow(flow_mixed_braces) == flow) error stop 'to_flow'
end block basic_flow end block basic_flow
multi_line_flow1: block
character(len=*), parameter :: flow_multi = &
"%YAML 1.1"//IO_EOL//&
"---"//IO_EOL//&
"a: [b,"//IO_EOL//&
"c: "//IO_EOL//&
"d, e]"//IO_EOL
character(len=*), parameter :: flow = &
"{a: [b, {c: d}, e]}"
if( .not. to_flow(flow_multi) == flow) error stop 'to_flow'
end block multi_line_flow1
multi_line_flow2: block
character(len=*), parameter :: flow_multi = &
"%YAML 1.1"//IO_EOL//&
"---"//IO_EOL//&
"-"//IO_EOL//&
" a: {b:"//IO_EOL//&
"[c,"//IO_EOL//&
"d"//IO_EOL//&
"e, f]}"//IO_EOL
character(len=*), parameter :: flow = &
"[{a: {b: [c, d e, f]}}]"
if( .not. to_flow(flow_multi) == flow) error stop 'to_flow'
end block multi_line_flow2
basic_mixed: block basic_mixed: block
character(len=*), parameter :: block_flow = & character(len=*), parameter :: block_flow = &
"%YAML 1.1"//IO_EOL//& "%YAML 1.1"//IO_EOL//&

View File

@ -952,6 +952,9 @@ function tNode_get_byKey_asIndex(self,key) result(keyIndex)
endif endif
enddo enddo
if(keyIndex == -1) call IO_error(140,ext_msg=key)
end function tNode_get_byKey_asIndex end function tNode_get_byKey_asIndex

View File

@ -452,11 +452,11 @@ subroutine constitutive_init
PhaseLoop2:do p = 1,phases%length PhaseLoop2:do p = 1,phases%length
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! partition and initialize state ! partition and initialize state
plasticState(p)%partionedState0 = plasticState(p)%state0 plasticState(p)%partitionedState0 = plasticState(p)%state0
plasticState(p)%state = plasticState(p)%partionedState0 plasticState(p)%state = plasticState(p)%partitionedState0
forall(s = 1:phase_Nsources(p)) forall(s = 1:phase_Nsources(p))
sourceState(p)%p(s)%partionedState0 = sourceState(p)%p(s)%state0 sourceState(p)%p(s)%partitionedState0 = sourceState(p)%p(s)%state0
sourceState(p)%p(s)%state = sourceState(p)%p(s)%partionedState0 sourceState(p)%p(s)%state = sourceState(p)%p(s)%partitionedState0
end forall end forall
constitutive_source_maxSizeDotState = max(constitutive_source_maxSizeDotState, & constitutive_source_maxSizeDotState = max(constitutive_source_maxSizeDotState, &
@ -922,7 +922,7 @@ subroutine constitutive_allocateState(state, &
allocate(state%atol (sizeState), source=0.0_pReal) allocate(state%atol (sizeState), source=0.0_pReal)
allocate(state%state0 (sizeState,NipcMyPhase), source=0.0_pReal) allocate(state%state0 (sizeState,NipcMyPhase), source=0.0_pReal)
allocate(state%partionedState0(sizeState,NipcMyPhase), source=0.0_pReal) allocate(state%partitionedState0(sizeState,NipcMyPhase), source=0.0_pReal)
allocate(state%subState0 (sizeState,NipcMyPhase), source=0.0_pReal) allocate(state%subState0 (sizeState,NipcMyPhase), source=0.0_pReal)
allocate(state%state (sizeState,NipcMyPhase), source=0.0_pReal) allocate(state%state (sizeState,NipcMyPhase), source=0.0_pReal)

View File

@ -44,30 +44,30 @@ module crystallite
! !
crystallite_Fp, & !< current plastic def grad (end of converged time step) crystallite_Fp, & !< current plastic def grad (end of converged time step)
crystallite_Fp0, & !< plastic def grad at start of FE inc crystallite_Fp0, & !< plastic def grad at start of FE inc
crystallite_partionedFp0,& !< plastic def grad at start of homog inc crystallite_partitionedFp0,& !< plastic def grad at start of homog inc
crystallite_subFp0,& !< plastic def grad at start of crystallite inc crystallite_subFp0,& !< plastic def grad at start of crystallite inc
! !
crystallite_Fi, & !< current intermediate def grad (end of converged time step) crystallite_Fi, & !< current intermediate def grad (end of converged time step)
crystallite_Fi0, & !< intermediate def grad at start of FE inc crystallite_Fi0, & !< intermediate def grad at start of FE inc
crystallite_partionedFi0,& !< intermediate def grad at start of homog inc crystallite_partitionedFi0,& !< intermediate def grad at start of homog inc
crystallite_subFi0,& !< intermediate def grad at start of crystallite inc crystallite_subFi0,& !< intermediate def grad at start of crystallite inc
! !
crystallite_Lp0, & !< plastic velocitiy grad at start of FE inc crystallite_Lp0, & !< plastic velocitiy grad at start of FE inc
crystallite_partionedLp0, & !< plastic velocity grad at start of homog inc crystallite_partitionedLp0, & !< plastic velocity grad at start of homog inc
! !
crystallite_Li, & !< current intermediate velocitiy grad (end of converged time step) crystallite_Li, & !< current intermediate velocitiy grad (end of converged time step)
crystallite_Li0, & !< intermediate velocitiy grad at start of FE inc crystallite_Li0, & !< intermediate velocitiy grad at start of FE inc
crystallite_partionedLi0, & !< intermediate velocity grad at start of homog inc crystallite_partitionedLi0, & !< intermediate velocity grad at start of homog inc
! !
crystallite_S0, & !< 2nd Piola-Kirchhoff stress vector at start of FE inc crystallite_S0, & !< 2nd Piola-Kirchhoff stress vector at start of FE inc
crystallite_partionedS0 !< 2nd Piola-Kirchhoff stress vector at start of homog inc crystallite_partitionedS0 !< 2nd Piola-Kirchhoff stress vector at start of homog inc
real(pReal), dimension(:,:,:,:,:), allocatable, public, protected :: & real(pReal), dimension(:,:,:,:,:), allocatable, public, protected :: &
crystallite_P, & !< 1st Piola-Kirchhoff stress per grain crystallite_P, & !< 1st Piola-Kirchhoff stress per grain
crystallite_Lp, & !< current plastic velocitiy grad (end of converged time step) crystallite_Lp, & !< current plastic velocitiy grad (end of converged time step)
crystallite_S, & !< current 2nd Piola-Kirchhoff stress vector (end of converged time step) crystallite_S, & !< current 2nd Piola-Kirchhoff stress vector (end of converged time step)
crystallite_partionedF0 !< def grad at start of homog inc crystallite_partitionedF0 !< def grad at start of homog inc
real(pReal), dimension(:,:,:,:,:), allocatable, public :: & real(pReal), dimension(:,:,:,:,:), allocatable, public :: &
crystallite_partionedF !< def grad to be reached at end of homog inc crystallite_partitionedF !< def grad to be reached at end of homog inc
logical, dimension(:,:,:), allocatable, public :: & logical, dimension(:,:,:), allocatable, public :: &
crystallite_requested !< used by upper level (homogenization) to request crystallite calculation crystallite_requested !< used by upper level (homogenization) to request crystallite calculation
@ -166,20 +166,20 @@ subroutine crystallite_init
iMax = discretization_nIP iMax = discretization_nIP
eMax = discretization_nElem eMax = discretization_nElem
allocate(crystallite_partionedF(3,3,cMax,iMax,eMax),source=0.0_pReal) allocate(crystallite_partitionedF(3,3,cMax,iMax,eMax),source=0.0_pReal)
allocate(crystallite_S0, & allocate(crystallite_S0, &
crystallite_F0, crystallite_Fi0,crystallite_Fp0, & crystallite_F0, crystallite_Fi0,crystallite_Fp0, &
crystallite_Li0,crystallite_Lp0, & crystallite_Li0,crystallite_Lp0, &
crystallite_partionedS0, & crystallite_partitionedS0, &
crystallite_partionedF0,crystallite_partionedFp0,crystallite_partionedFi0, & crystallite_partitionedF0,crystallite_partitionedFp0,crystallite_partitionedFi0, &
crystallite_partionedLp0,crystallite_partionedLi0, & crystallite_partitionedLp0,crystallite_partitionedLi0, &
crystallite_S,crystallite_P, & crystallite_S,crystallite_P, &
crystallite_Fe,crystallite_Fi,crystallite_Fp, & crystallite_Fe,crystallite_Fi,crystallite_Fp, &
crystallite_Li,crystallite_Lp, & crystallite_Li,crystallite_Lp, &
crystallite_subF,crystallite_subF0, & crystallite_subF,crystallite_subF0, &
crystallite_subFp0,crystallite_subFi0, & crystallite_subFp0,crystallite_subFi0, &
source = crystallite_partionedF) source = crystallite_partitionedF)
allocate(crystallite_dt(cMax,iMax,eMax),source=0.0_pReal) allocate(crystallite_dt(cMax,iMax,eMax),source=0.0_pReal)
allocate(crystallite_subdt,crystallite_subFrac,crystallite_subStep, & allocate(crystallite_subdt,crystallite_subFrac,crystallite_subStep, &
@ -269,10 +269,10 @@ subroutine crystallite_init
!$OMP END PARALLEL DO !$OMP END PARALLEL DO
crystallite_partionedFp0 = crystallite_Fp0 crystallite_partitionedFp0 = crystallite_Fp0
crystallite_partionedFi0 = crystallite_Fi0 crystallite_partitionedFi0 = crystallite_Fi0
crystallite_partionedF0 = crystallite_F0 crystallite_partitionedF0 = crystallite_F0
crystallite_partionedF = crystallite_F0 crystallite_partitionedF = crystallite_F0
call crystallite_orientations() call crystallite_orientations()
@ -280,8 +280,8 @@ subroutine crystallite_init
do e = FEsolving_execElem(1),FEsolving_execElem(2) do e = FEsolving_execElem(1),FEsolving_execElem(2)
do i = FEsolving_execIP(1),FEsolving_execIP(2) do i = FEsolving_execIP(1),FEsolving_execIP(2)
do c = 1,homogenization_Ngrains(material_homogenizationAt(e)) do c = 1,homogenization_Ngrains(material_homogenizationAt(e))
call constitutive_dependentState(crystallite_partionedF0(1:3,1:3,c,i,e), & call constitutive_dependentState(crystallite_partitionedF0(1:3,1:3,c,i,e), &
crystallite_partionedFp0(1:3,1:3,c,i,e), & crystallite_partitionedFp0(1:3,1:3,c,i,e), &
c,i,e) ! update dependent state variables to be consistent with basic states c,i,e) ! update dependent state variables to be consistent with basic states
enddo enddo
enddo enddo
@ -325,8 +325,8 @@ function crystallite_stress()
todo = .false. todo = .false.
subLp0 = crystallite_partionedLp0 subLp0 = crystallite_partitionedLp0
subLi0 = crystallite_partionedLi0 subLi0 = crystallite_partitionedLi0
@ -338,15 +338,15 @@ function crystallite_stress()
do i = FEsolving_execIP(1),FEsolving_execIP(2); do c = 1,homogenization_Ngrains(material_homogenizationAt(e)) do i = FEsolving_execIP(1),FEsolving_execIP(2); do c = 1,homogenization_Ngrains(material_homogenizationAt(e))
homogenizationRequestsCalculation: if (crystallite_requested(c,i,e)) then homogenizationRequestsCalculation: if (crystallite_requested(c,i,e)) then
plasticState (material_phaseAt(c,e))%subState0( :,material_phaseMemberAt(c,i,e)) = & plasticState (material_phaseAt(c,e))%subState0( :,material_phaseMemberAt(c,i,e)) = &
plasticState (material_phaseAt(c,e))%partionedState0(:,material_phaseMemberAt(c,i,e)) plasticState (material_phaseAt(c,e))%partitionedState0(:,material_phaseMemberAt(c,i,e))
do s = 1, phase_Nsources(material_phaseAt(c,e)) do s = 1, phase_Nsources(material_phaseAt(c,e))
sourceState(material_phaseAt(c,e))%p(s)%subState0( :,material_phaseMemberAt(c,i,e)) = & sourceState(material_phaseAt(c,e))%p(s)%subState0( :,material_phaseMemberAt(c,i,e)) = &
sourceState(material_phaseAt(c,e))%p(s)%partionedState0(:,material_phaseMemberAt(c,i,e)) sourceState(material_phaseAt(c,e))%p(s)%partitionedState0(:,material_phaseMemberAt(c,i,e))
enddo enddo
crystallite_subFp0(1:3,1:3,c,i,e) = crystallite_partionedFp0(1:3,1:3,c,i,e) crystallite_subFp0(1:3,1:3,c,i,e) = crystallite_partitionedFp0(1:3,1:3,c,i,e)
crystallite_subFi0(1:3,1:3,c,i,e) = crystallite_partionedFi0(1:3,1:3,c,i,e) crystallite_subFi0(1:3,1:3,c,i,e) = crystallite_partitionedFi0(1:3,1:3,c,i,e)
crystallite_subF0(1:3,1:3,c,i,e) = crystallite_partionedF0(1:3,1:3,c,i,e) crystallite_subF0(1:3,1:3,c,i,e) = crystallite_partitionedF0(1:3,1:3,c,i,e)
crystallite_subFrac(c,i,e) = 0.0_pReal crystallite_subFrac(c,i,e) = 0.0_pReal
crystallite_subStep(c,i,e) = 1.0_pReal/num%subStepSizeCryst crystallite_subStep(c,i,e) = 1.0_pReal/num%subStepSizeCryst
todo(c,i,e) = .true. todo(c,i,e) = .true.
@ -426,8 +426,8 @@ function crystallite_stress()
! prepare for integration ! prepare for integration
if (todo(c,i,e)) then if (todo(c,i,e)) then
crystallite_subF(1:3,1:3,c,i,e) = crystallite_subF0(1:3,1:3,c,i,e) & crystallite_subF(1:3,1:3,c,i,e) = crystallite_subF0(1:3,1:3,c,i,e) &
+ crystallite_subStep(c,i,e) *( crystallite_partionedF (1:3,1:3,c,i,e) & + crystallite_subStep(c,i,e) *( crystallite_partitionedF (1:3,1:3,c,i,e) &
-crystallite_partionedF0(1:3,1:3,c,i,e)) -crystallite_partitionedF0(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_Fe(1:3,1:3,c,i,e) = matmul(matmul(crystallite_subF(1:3,1:3,c,i,e), &
math_inv33(crystallite_Fp(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))) math_inv33(crystallite_Fi(1:3,1:3,c,i,e)))
@ -441,8 +441,6 @@ function crystallite_stress()
enddo elementLooping3 enddo elementLooping3
!$OMP END PARALLEL DO !$OMP END PARALLEL DO
call nonlocalConvergenceCheck
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! integrate --- requires fully defined state array (basic + dependent state) ! integrate --- requires fully defined state array (basic + dependent state)
where(.not. crystallite_converged .and. crystallite_subStep > num%subStepMinCryst) & ! do not try non-converged but fully cutbacked any further where(.not. crystallite_converged .and. crystallite_subStep > num%subStepMinCryst) & ! do not try non-converged but fully cutbacked any further
@ -475,17 +473,17 @@ subroutine crystallite_initializeRestorationPoints(i,e)
s s
do c = 1,homogenization_Ngrains(material_homogenizationAt(e)) do c = 1,homogenization_Ngrains(material_homogenizationAt(e))
crystallite_partionedFp0(1:3,1:3,c,i,e) = crystallite_Fp0(1:3,1:3,c,i,e) crystallite_partitionedFp0(1:3,1:3,c,i,e) = crystallite_Fp0(1:3,1:3,c,i,e)
crystallite_partionedLp0(1:3,1:3,c,i,e) = crystallite_Lp0(1:3,1:3,c,i,e) crystallite_partitionedLp0(1:3,1:3,c,i,e) = crystallite_Lp0(1:3,1:3,c,i,e)
crystallite_partionedFi0(1:3,1:3,c,i,e) = crystallite_Fi0(1:3,1:3,c,i,e) crystallite_partitionedFi0(1:3,1:3,c,i,e) = crystallite_Fi0(1:3,1:3,c,i,e)
crystallite_partionedLi0(1:3,1:3,c,i,e) = crystallite_Li0(1:3,1:3,c,i,e) crystallite_partitionedLi0(1:3,1:3,c,i,e) = crystallite_Li0(1:3,1:3,c,i,e)
crystallite_partionedF0(1:3,1:3,c,i,e) = crystallite_F0(1:3,1:3,c,i,e) crystallite_partitionedF0(1:3,1:3,c,i,e) = crystallite_F0(1:3,1:3,c,i,e)
crystallite_partionedS0(1:3,1:3,c,i,e) = crystallite_S0(1:3,1:3,c,i,e) crystallite_partitionedS0(1:3,1:3,c,i,e) = crystallite_S0(1:3,1:3,c,i,e)
plasticState(material_phaseAt(c,e))%partionedState0(:,material_phasememberAt(c,i,e)) = & plasticState(material_phaseAt(c,e))%partitionedState0(:,material_phasememberAt(c,i,e)) = &
plasticState(material_phaseAt(c,e))%state0( :,material_phasememberAt(c,i,e)) plasticState(material_phaseAt(c,e))%state0( :,material_phasememberAt(c,i,e))
do s = 1, phase_Nsources(material_phaseAt(c,e)) do s = 1, phase_Nsources(material_phaseAt(c,e))
sourceState(material_phaseAt(c,e))%p(s)%partionedState0(:,material_phasememberAt(c,i,e)) = & sourceState(material_phaseAt(c,e))%p(s)%partitionedState0(:,material_phasememberAt(c,i,e)) = &
sourceState(material_phaseAt(c,e))%p(s)%state0( :,material_phasememberAt(c,i,e)) sourceState(material_phaseAt(c,e))%p(s)%state0( :,material_phasememberAt(c,i,e))
enddo enddo
enddo enddo
@ -506,17 +504,17 @@ subroutine crystallite_windForward(i,e)
s s
do c = 1,homogenization_Ngrains(material_homogenizationAt(e)) do c = 1,homogenization_Ngrains(material_homogenizationAt(e))
crystallite_partionedF0 (1:3,1:3,c,i,e) = crystallite_partionedF(1:3,1:3,c,i,e) crystallite_partitionedF0 (1:3,1:3,c,i,e) = crystallite_partitionedF(1:3,1:3,c,i,e)
crystallite_partionedFp0(1:3,1:3,c,i,e) = crystallite_Fp (1:3,1:3,c,i,e) crystallite_partitionedFp0(1:3,1:3,c,i,e) = crystallite_Fp (1:3,1:3,c,i,e)
crystallite_partionedLp0(1:3,1:3,c,i,e) = crystallite_Lp (1:3,1:3,c,i,e) crystallite_partitionedLp0(1:3,1:3,c,i,e) = crystallite_Lp (1:3,1:3,c,i,e)
crystallite_partionedFi0(1:3,1:3,c,i,e) = crystallite_Fi (1:3,1:3,c,i,e) crystallite_partitionedFi0(1:3,1:3,c,i,e) = crystallite_Fi (1:3,1:3,c,i,e)
crystallite_partionedLi0(1:3,1:3,c,i,e) = crystallite_Li (1:3,1:3,c,i,e) crystallite_partitionedLi0(1:3,1:3,c,i,e) = crystallite_Li (1:3,1:3,c,i,e)
crystallite_partionedS0 (1:3,1:3,c,i,e) = crystallite_S (1:3,1:3,c,i,e) crystallite_partitionedS0 (1:3,1:3,c,i,e) = crystallite_S (1:3,1:3,c,i,e)
plasticState (material_phaseAt(c,e))%partionedState0(:,material_phasememberAt(c,i,e)) = & plasticState (material_phaseAt(c,e))%partitionedState0(:,material_phasememberAt(c,i,e)) = &
plasticState (material_phaseAt(c,e))%state (:,material_phasememberAt(c,i,e)) plasticState (material_phaseAt(c,e))%state (:,material_phasememberAt(c,i,e))
do s = 1, phase_Nsources(material_phaseAt(c,e)) do s = 1, phase_Nsources(material_phaseAt(c,e))
sourceState(material_phaseAt(c,e))%p(s)%partionedState0(:,material_phasememberAt(c,i,e)) = & sourceState(material_phaseAt(c,e))%p(s)%partitionedState0(:,material_phasememberAt(c,i,e)) = &
sourceState(material_phaseAt(c,e))%p(s)%state (:,material_phasememberAt(c,i,e)) sourceState(material_phaseAt(c,e))%p(s)%state (:,material_phasememberAt(c,i,e))
enddo enddo
enddo enddo
@ -540,18 +538,18 @@ subroutine crystallite_restore(i,e,includeL)
do c = 1,homogenization_Ngrains(material_homogenizationAt(e)) do c = 1,homogenization_Ngrains(material_homogenizationAt(e))
if (includeL) then if (includeL) then
crystallite_Lp(1:3,1:3,c,i,e) = crystallite_partionedLp0(1:3,1:3,c,i,e) crystallite_Lp(1:3,1:3,c,i,e) = crystallite_partitionedLp0(1:3,1:3,c,i,e)
crystallite_Li(1:3,1:3,c,i,e) = crystallite_partionedLi0(1:3,1:3,c,i,e) crystallite_Li(1:3,1:3,c,i,e) = crystallite_partitionedLi0(1:3,1:3,c,i,e)
endif ! maybe protecting everything from overwriting makes more sense endif ! maybe protecting everything from overwriting makes more sense
crystallite_Fp(1:3,1:3,c,i,e) = crystallite_partionedFp0(1:3,1:3,c,i,e) crystallite_Fp(1:3,1:3,c,i,e) = crystallite_partitionedFp0(1:3,1:3,c,i,e)
crystallite_Fi(1:3,1:3,c,i,e) = crystallite_partionedFi0(1:3,1:3,c,i,e) crystallite_Fi(1:3,1:3,c,i,e) = crystallite_partitionedFi0(1:3,1:3,c,i,e)
crystallite_S (1:3,1:3,c,i,e) = crystallite_partionedS0 (1:3,1:3,c,i,e) crystallite_S (1:3,1:3,c,i,e) = crystallite_partitionedS0 (1:3,1:3,c,i,e)
plasticState (material_phaseAt(c,e))%state( :,material_phasememberAt(c,i,e)) = & plasticState (material_phaseAt(c,e))%state( :,material_phasememberAt(c,i,e)) = &
plasticState (material_phaseAt(c,e))%partionedState0(:,material_phasememberAt(c,i,e)) plasticState (material_phaseAt(c,e))%partitionedState0(:,material_phasememberAt(c,i,e))
do s = 1, phase_Nsources(material_phaseAt(c,e)) do s = 1, phase_Nsources(material_phaseAt(c,e))
sourceState(material_phaseAt(c,e))%p(s)%state( :,material_phasememberAt(c,i,e)) = & sourceState(material_phaseAt(c,e))%p(s)%state( :,material_phasememberAt(c,i,e)) = &
sourceState(material_phaseAt(c,e))%p(s)%partionedState0(:,material_phasememberAt(c,i,e)) sourceState(material_phaseAt(c,e))%p(s)%partitionedState0(:,material_phasememberAt(c,i,e))
enddo enddo
enddo enddo
@ -758,7 +756,7 @@ subroutine crystallite_results
do o = 1, size(output_constituent(p)%label) do o = 1, size(output_constituent(p)%label)
select case (output_constituent(p)%label(o)) select case (output_constituent(p)%label(o))
case('F') case('F')
selected_tensors = select_tensors(crystallite_partionedF,p) selected_tensors = select_tensors(crystallite_partitionedF,p)
call results_writeDataset(group,selected_tensors,output_constituent(p)%label(o),& call results_writeDataset(group,selected_tensors,output_constituent(p)%label(o),&
'deformation gradient','1') 'deformation gradient','1')
case('Fe') case('Fe')
@ -943,7 +941,7 @@ function integrateStress(ipc,ip,el,timeFraction) result(broken)
F = crystallite_subF(1:3,1:3,ipc,ip,el) F = crystallite_subF(1:3,1:3,ipc,ip,el)
endif endif
call constitutive_dependentState(crystallite_partionedF(1:3,1:3,ipc,ip,el), & call constitutive_dependentState(crystallite_partitionedF(1:3,1:3,ipc,ip,el), &
crystallite_Fp(1:3,1:3,ipc,ip,el),ipc,ip,el) crystallite_Fp(1:3,1:3,ipc,ip,el),ipc,ip,el)
Lpguess = crystallite_Lp(1:3,1:3,ipc,ip,el) ! take as first guess Lpguess = crystallite_Lp(1:3,1:3,ipc,ip,el) ! take as first guess
@ -1120,9 +1118,9 @@ subroutine integrateStateFPI(g,i,e)
c = material_phaseMemberAt(g,i,e) c = material_phaseMemberAt(g,i,e)
broken = constitutive_collectDotState(crystallite_S(1:3,1:3,g,i,e), & broken = constitutive_collectDotState(crystallite_S(1:3,1:3,g,i,e), &
crystallite_partionedF0, & crystallite_partitionedF0, &
crystallite_Fi(1:3,1:3,g,i,e), & crystallite_Fi(1:3,1:3,g,i,e), &
crystallite_partionedFp0, & crystallite_partitionedFp0, &
crystallite_subdt(g,i,e), g,i,e,p,c) crystallite_subdt(g,i,e), g,i,e,p,c)
if(broken) return if(broken) return
@ -1152,9 +1150,9 @@ subroutine integrateStateFPI(g,i,e)
if(broken) exit iteration if(broken) exit iteration
broken = constitutive_collectDotState(crystallite_S(1:3,1:3,g,i,e), & broken = constitutive_collectDotState(crystallite_S(1:3,1:3,g,i,e), &
crystallite_partionedF0, & crystallite_partitionedF0, &
crystallite_Fi(1:3,1:3,g,i,e), & crystallite_Fi(1:3,1:3,g,i,e), &
crystallite_partionedFp0, & crystallite_partitionedFp0, &
crystallite_subdt(g,i,e), g,i,e,p,c) crystallite_subdt(g,i,e), g,i,e,p,c)
if(broken) exit iteration if(broken) exit iteration
@ -1243,9 +1241,9 @@ subroutine integrateStateEuler(g,i,e)
c = material_phaseMemberAt(g,i,e) c = material_phaseMemberAt(g,i,e)
broken = constitutive_collectDotState(crystallite_S(1:3,1:3,g,i,e), & broken = constitutive_collectDotState(crystallite_S(1:3,1:3,g,i,e), &
crystallite_partionedF0, & crystallite_partitionedF0, &
crystallite_Fi(1:3,1:3,g,i,e), & crystallite_Fi(1:3,1:3,g,i,e), &
crystallite_partionedFp0, & crystallite_partitionedFp0, &
crystallite_subdt(g,i,e), g,i,e,p,c) crystallite_subdt(g,i,e), g,i,e,p,c)
if(broken) return if(broken) return
@ -1296,9 +1294,9 @@ subroutine integrateStateAdaptiveEuler(g,i,e)
c = material_phaseMemberAt(g,i,e) c = material_phaseMemberAt(g,i,e)
broken = constitutive_collectDotState(crystallite_S(1:3,1:3,g,i,e), & broken = constitutive_collectDotState(crystallite_S(1:3,1:3,g,i,e), &
crystallite_partionedF0, & crystallite_partitionedF0, &
crystallite_Fi(1:3,1:3,g,i,e), & crystallite_Fi(1:3,1:3,g,i,e), &
crystallite_partionedFp0, & crystallite_partitionedFp0, &
crystallite_subdt(g,i,e), g,i,e,p,c) crystallite_subdt(g,i,e), g,i,e,p,c)
if(broken) return if(broken) return
@ -1325,9 +1323,9 @@ subroutine integrateStateAdaptiveEuler(g,i,e)
if(broken) return if(broken) return
broken = constitutive_collectDotState(crystallite_S(1:3,1:3,g,i,e), & broken = constitutive_collectDotState(crystallite_S(1:3,1:3,g,i,e), &
crystallite_partionedF0, & crystallite_partitionedF0, &
crystallite_Fi(1:3,1:3,g,i,e), & crystallite_Fi(1:3,1:3,g,i,e), &
crystallite_partionedFp0, & crystallite_partitionedFp0, &
crystallite_subdt(g,i,e), g,i,e,p,c) crystallite_subdt(g,i,e), g,i,e,p,c)
if(broken) return if(broken) return
@ -1434,9 +1432,9 @@ subroutine integrateStateRK(g,i,e,A,B,CC,DB)
c = material_phaseMemberAt(g,i,e) c = material_phaseMemberAt(g,i,e)
broken = constitutive_collectDotState(crystallite_S(1:3,1:3,g,i,e), & broken = constitutive_collectDotState(crystallite_S(1:3,1:3,g,i,e), &
crystallite_partionedF0, & crystallite_partitionedF0, &
crystallite_Fi(1:3,1:3,g,i,e), & crystallite_Fi(1:3,1:3,g,i,e), &
crystallite_partionedFp0, & crystallite_partitionedFp0, &
crystallite_subdt(g,i,e), g,i,e,p,c) crystallite_subdt(g,i,e), g,i,e,p,c)
if(broken) return if(broken) return
@ -1476,9 +1474,9 @@ subroutine integrateStateRK(g,i,e,A,B,CC,DB)
if(broken) exit if(broken) exit
broken = constitutive_collectDotState(crystallite_S(1:3,1:3,g,i,e), & broken = constitutive_collectDotState(crystallite_S(1:3,1:3,g,i,e), &
crystallite_partionedF0, & crystallite_partitionedF0, &
crystallite_Fi(1:3,1:3,g,i,e), & crystallite_Fi(1:3,1:3,g,i,e), &
crystallite_partionedFp0, & crystallite_partitionedFp0, &
crystallite_subdt(g,i,e)*CC(stage), g,i,e,p,c) crystallite_subdt(g,i,e)*CC(stage), g,i,e,p,c)
if(broken) exit if(broken) exit
@ -1526,38 +1524,6 @@ subroutine integrateStateRK(g,i,e,A,B,CC,DB)
end subroutine integrateStateRK end subroutine integrateStateRK
!--------------------------------------------------------------------------------------------------
!> @brief sets convergence flag for nonlocal calculations
!> @details one non-converged nonlocal sets all other nonlocals to non-converged to trigger cut back
!--------------------------------------------------------------------------------------------------
subroutine nonlocalConvergenceCheck
integer :: e,i,p
logical :: nonlocal_broken
nonlocal_broken = .false.
!$OMP PARALLEL DO PRIVATE(p)
do e = FEsolving_execElem(1),FEsolving_execElem(2)
p = material_phaseAt(1,e)
do i = FEsolving_execIP(1),FEsolving_execIP(2)
if(plasticState(p)%nonlocal .and. .not. crystallite_converged(1,i,e)) nonlocal_broken = .true.
enddo
enddo
!$OMP END PARALLEL DO
if(.not. nonlocal_broken) return
!$OMP PARALLEL DO PRIVATE(p)
do e = FEsolving_execElem(1),FEsolving_execElem(2)
p = material_phaseAt(1,e)
do i = FEsolving_execIP(1),FEsolving_execIP(2)
if(plasticState(p)%nonlocal) crystallite_converged(1,i,e) = .false.
enddo
enddo
!$OMP END PARALLEL DO
end subroutine nonlocalConvergenceCheck
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief determines whether a point is converged !> @brief determines whether a point is converged
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
@ -1590,7 +1556,7 @@ subroutine crystallite_restartWrite
write(fileName,'(a,i0,a)') trim(getSolverJobName())//'_',worldrank,'.hdf5' write(fileName,'(a,i0,a)') trim(getSolverJobName())//'_',worldrank,'.hdf5'
fileHandle = HDF5_openFile(fileName,'a') fileHandle = HDF5_openFile(fileName,'a')
call HDF5_write(fileHandle,crystallite_partionedF,'F') call HDF5_write(fileHandle,crystallite_partitionedF,'F')
call HDF5_write(fileHandle,crystallite_Fp, 'Fp') call HDF5_write(fileHandle,crystallite_Fp, 'Fp')
call HDF5_write(fileHandle,crystallite_Fi, 'Fi') call HDF5_write(fileHandle,crystallite_Fi, 'Fi')
call HDF5_write(fileHandle,crystallite_Lp, 'Lp') call HDF5_write(fileHandle,crystallite_Lp, 'Lp')
@ -1665,7 +1631,7 @@ subroutine crystallite_forward
integer :: i, j integer :: i, j
crystallite_F0 = crystallite_partionedF crystallite_F0 = crystallite_partitionedF
crystallite_Fp0 = crystallite_Fp crystallite_Fp0 = crystallite_Fp
crystallite_Lp0 = crystallite_Lp crystallite_Lp0 = crystallite_Lp
crystallite_Fi0 = crystallite_Fi crystallite_Fi0 = crystallite_Fi

View File

@ -404,16 +404,16 @@ subroutine partitionDeformation(subF,ip,el)
chosenHomogenization: select case(homogenization_type(material_homogenizationAt(el))) chosenHomogenization: select case(homogenization_type(material_homogenizationAt(el)))
case (HOMOGENIZATION_NONE_ID) chosenHomogenization case (HOMOGENIZATION_NONE_ID) chosenHomogenization
crystallite_partionedF(1:3,1:3,1,ip,el) = subF crystallite_partitionedF(1:3,1:3,1,ip,el) = subF
case (HOMOGENIZATION_ISOSTRAIN_ID) chosenHomogenization case (HOMOGENIZATION_ISOSTRAIN_ID) chosenHomogenization
call mech_isostrain_partitionDeformation(& call mech_isostrain_partitionDeformation(&
crystallite_partionedF(1:3,1:3,1:homogenization_Ngrains(material_homogenizationAt(el)),ip,el), & crystallite_partitionedF(1:3,1:3,1:homogenization_Ngrains(material_homogenizationAt(el)),ip,el), &
subF) subF)
case (HOMOGENIZATION_RGC_ID) chosenHomogenization case (HOMOGENIZATION_RGC_ID) chosenHomogenization
call mech_RGC_partitionDeformation(& call mech_RGC_partitionDeformation(&
crystallite_partionedF(1:3,1:3,1:homogenization_Ngrains(material_homogenizationAt(el)),ip,el), & crystallite_partitionedF(1:3,1:3,1:homogenization_Ngrains(material_homogenizationAt(el)),ip,el), &
subF,& subF,&
ip, & ip, &
el) el)
@ -448,8 +448,8 @@ function updateState(subdt,subF,ip,el)
updateState = & updateState = &
updateState .and. & updateState .and. &
mech_RGC_updateState(crystallite_P(1:3,1:3,1:homogenization_Ngrains(material_homogenizationAt(el)),ip,el), & mech_RGC_updateState(crystallite_P(1:3,1:3,1:homogenization_Ngrains(material_homogenizationAt(el)),ip,el), &
crystallite_partionedF(1:3,1:3,1:homogenization_Ngrains(material_homogenizationAt(el)),ip,el), & crystallite_partitionedF(1:3,1:3,1:homogenization_Ngrains(material_homogenizationAt(el)),ip,el), &
crystallite_partionedF0(1:3,1:3,1:homogenization_Ngrains(material_homogenizationAt(el)),ip,el),& crystallite_partitionedF0(1:3,1:3,1:homogenization_Ngrains(material_homogenizationAt(el)),ip,el),&
subF,& subF,&
subdt, & subdt, &
dPdFs, & dPdFs, &

View File

@ -212,7 +212,7 @@ end subroutine mech_RGC_init
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
module subroutine mech_RGC_partitionDeformation(F,avgF,instance,of) module subroutine mech_RGC_partitionDeformation(F,avgF,instance,of)
real(pReal), dimension (:,:,:), intent(out) :: F !< partioned F per grain real(pReal), dimension (:,:,:), intent(out) :: F !< partitioned F per grain
real(pReal), dimension (3,3), intent(in) :: avgF !< averaged F real(pReal), dimension (3,3), intent(in) :: avgF !< averaged F
integer, intent(in) :: & integer, intent(in) :: &
@ -867,7 +867,7 @@ module procedure mech_RGC_updateState
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine grainDeformation(F, avgF, instance, of) subroutine grainDeformation(F, avgF, instance, of)
real(pReal), dimension(:,:,:), intent(out) :: F !< partioned F per grain real(pReal), dimension(:,:,:), intent(out) :: F !< partitioned F per grain
real(pReal), dimension(:,:), intent(in) :: avgF !< averaged F real(pReal), dimension(:,:), intent(in) :: avgF !< averaged F
integer, intent(in) :: & integer, intent(in) :: &

View File

@ -47,7 +47,7 @@ module prec
dotState, & !< rate of state change dotState, & !< rate of state change
deltaState !< increment of state change deltaState !< increment of state change
real(pReal), allocatable, dimension(:,:) :: & real(pReal), allocatable, dimension(:,:) :: &
partionedState0, & partitionedState0, &
subState0 subState0
end type end type