Merge branch 'XDMF-improvements' into 'development'

Xdmf improvements

See merge request damask/DAMASK!293
This commit is contained in:
Vitesh 2020-12-02 12:39:07 +01:00
commit 5726f0bce9
4 changed files with 1670 additions and 15 deletions

@ -1 +1 @@
Subproject commit 751f96155294e449b31c5d4913fea7bc02ce81b1 Subproject commit 68cde52291ebb683ca6f610879f2ae28372597a7

View File

@ -61,7 +61,7 @@ class Result:
self.increments = [increments_unsorted[i] for i in sorted(increments_unsorted)] self.increments = [increments_unsorted[i] for i in sorted(increments_unsorted)]
self.times = [round(f[i].attrs['time/s'],12) for i in self.increments] self.times = [round(f[i].attrs['time/s'],12) for i in self.increments]
self.N_materialpoints, self.N_constituents = np.shape(f['mapping/phase']) self.N_materialpoints, self.N_constituents = np.shape(f['mapping/phase'])
self.homogenizations = [m.decode() for m in np.unique(f['mapping/homogenization']['Name'])] self.homogenizations = [m.decode() for m in np.unique(f['mapping/homogenization']['Name'])]
self.phases = [c.decode() for c in np.unique(f['mapping/phase']['Name'])] self.phases = [c.decode() for c in np.unique(f['mapping/phase']['Name'])]
@ -1176,8 +1176,17 @@ class Result:
This works only for scalar, 3-vector and 3x3-tensor data. This works only for scalar, 3-vector and 3x3-tensor data.
Selection is not taken into account. Selection is not taken into account.
""" """
if self.N_constituents != 1 or not self.structured: if self.N_constituents != 1 or len(self.phases) != 1 or not self.structured:
raise NotImplementedError('XDMF only available for grid results with 1 constituent.') raise TypeError('XDMF output requires homogeneous grid')
attribute_type_map = defaultdict(lambda:'Matrix', ( ((),'Scalar'), ((3,),'Vector'), ((3,3),'Tensor')) )
def number_type_map(dtype):
if dtype in np.sctypes['int']: return 'Int'
if dtype in np.sctypes['uint']: return 'UInt'
if dtype in np.sctypes['float']: return 'Float'
xdmf=ET.Element('Xdmf') xdmf=ET.Element('Xdmf')
xdmf.attrib={'Version': '2.0', xdmf.attrib={'Version': '2.0',
@ -1227,8 +1236,6 @@ class Result:
delta.text="{} {} {}".format(*(self.size/self.grid)) delta.text="{} {} {}".format(*(self.size/self.grid))
type_map = defaultdict(lambda:'Matrix', ( ((),'Scalar'), ((3,),'Vector'), ((3,3),'Tensor')) )
with h5py.File(self.fname,'r') as f: with h5py.File(self.fname,'r') as f:
attributes.append(ET.SubElement(grid, 'Attribute')) attributes.append(ET.SubElement(grid, 'Attribute'))
attributes[-1].attrib={'Name': 'u / m', attributes[-1].attrib={'Name': 'u / m',
@ -1249,18 +1256,17 @@ class Result:
shape = f[name].shape[1:] shape = f[name].shape[1:]
dtype = f[name].dtype dtype = f[name].dtype
if dtype != np.float64: continue if dtype not in np.sctypes['int']+np.sctypes['uint']+np.sctypes['float']: continue
prec = f[name].dtype.itemsize
unit = f[name].attrs['Unit'] if h5py3 else f[name].attrs['Unit'].decode() unit = f[name].attrs['Unit'] if h5py3 else f[name].attrs['Unit'].decode()
attributes.append(ET.SubElement(grid, 'Attribute')) attributes.append(ET.SubElement(grid, 'Attribute'))
attributes[-1].attrib={'Name': name.split('/',2)[2]+f' / {unit}', attributes[-1].attrib={'Name': name.split('/',2)[2]+f' / {unit}',
'Center': 'Cell', 'Center': 'Cell',
'AttributeType': type_map[shape]} 'AttributeType': attribute_type_map[shape]}
data_items.append(ET.SubElement(attributes[-1], 'DataItem')) data_items.append(ET.SubElement(attributes[-1], 'DataItem'))
data_items[-1].attrib={'Format': 'HDF', data_items[-1].attrib={'Format': 'HDF',
'NumberType': 'Float', 'NumberType': number_type_map(dtype),
'Precision': f'{prec}', 'Precision': f'{dtype.itemsize}',
'Dimensions': '{} {} {} {}'.format(*self.grid,1 if shape == () else 'Dimensions': '{} {} {} {}'.format(*self.grid,1 if shape == () else
np.prod(shape))} np.prod(shape))}
data_items[-1].text=f'{os.path.split(self.fname)[1]}:{name}' data_items[-1].text=f'{os.path.split(self.fname)[1]}:{name}'
@ -1269,7 +1275,7 @@ class Result:
f.write(xml.dom.minidom.parseString(ET.tostring(xdmf).decode()).toprettyxml()) f.write(xml.dom.minidom.parseString(ET.tostring(xdmf).decode()).toprettyxml())
def save_vtk(self,labels=[],mode='cell'): def save_VTK(self,labels=[],mode='cell'):
""" """
Export to vtk cell/point data. Export to vtk cell/point data.

File diff suppressed because it is too large Load Diff

View File

@ -366,13 +366,24 @@ class TestResult:
@pytest.mark.parametrize('output',['F',[],['F','P']]) @pytest.mark.parametrize('output',['F',[],['F','P']])
def test_vtk(self,tmp_path,default,output): def test_vtk(self,tmp_path,default,output):
os.chdir(tmp_path) os.chdir(tmp_path)
default.save_vtk(output) default.save_VTK(output)
@pytest.mark.parametrize('mode',['point','cell']) @pytest.mark.parametrize('mode',['point','cell'])
def test_vtk_mode(self,tmp_path,single_phase,mode): def test_vtk_mode(self,tmp_path,single_phase,mode):
os.chdir(tmp_path) os.chdir(tmp_path)
single_phase.save_vtk(mode=mode) single_phase.save_VTK(mode=mode)
def test_XDMF(self,tmp_path,single_phase): def test_XDMF(self,tmp_path,single_phase,update,reference_dir):
for shape in [('scalar',()),('vector',(3,)),('tensor',(3,3)),('matrix',(12,))]:
for dtype in ['f4','f8','i1','i2','i4','i8','u1','u2','u4','u8']:
single_phase.add_calculation(f'{shape[0]}_{dtype}',f"np.ones(np.shape(#F#)[0:1]+{shape[1]},'{dtype}')")
fname = os.path.splitext(os.path.basename(single_phase.fname))[0]+'.xdmf'
os.chdir(tmp_path) os.chdir(tmp_path)
single_phase.save_XDMF() single_phase.save_XDMF()
if update:
shutil.copy(tmp_path/fname,reference_dir/fname)
assert sorted(open(tmp_path/fname).read()) == sorted(open(reference_dir/fname).read()) # XML is not ordered
def test_XDMF_invalid(self,default):
with pytest.raises(TypeError):
default.save_XDMF()