Merge branch 'user_defined_add_calculation' into 'development'
User defined add calculation See merge request damask/DAMASK!195
This commit is contained in:
commit
7824a61f2e
|
@ -466,6 +466,11 @@ class Result:
|
||||||
return f[self.get_dataset_location('orientation')[0]].attrs['Lattice'].astype('str') # np.bytes_ to string
|
return f[self.get_dataset_location('orientation')[0]].attrs['Lattice'].astype('str') # np.bytes_ to string
|
||||||
|
|
||||||
|
|
||||||
|
def enable_user_function(self,func):
|
||||||
|
globals()[func.__name__]=func
|
||||||
|
print(f'Function {func.__name__} enabled in add_calculation.')
|
||||||
|
|
||||||
|
|
||||||
def read_dataset(self,path,c=0,plain=False):
|
def read_dataset(self,path,c=0,plain=False):
|
||||||
"""
|
"""
|
||||||
Dataset for all points/cells.
|
Dataset for all points/cells.
|
||||||
|
@ -504,7 +509,7 @@ class Result:
|
||||||
else:
|
else:
|
||||||
return dataset
|
return dataset
|
||||||
|
|
||||||
|
@property
|
||||||
def cell_coordinates(self):
|
def cell_coordinates(self):
|
||||||
"""Return initial coordinates of the cell centers."""
|
"""Return initial coordinates of the cell centers."""
|
||||||
if self.structured:
|
if self.structured:
|
||||||
|
@ -513,6 +518,7 @@ class Result:
|
||||||
with h5py.File(self.fname,'r') as f:
|
with h5py.File(self.fname,'r') as f:
|
||||||
return f['geometry/x_c'][()]
|
return f['geometry/x_c'][()]
|
||||||
|
|
||||||
|
@property
|
||||||
def node_coordinates(self):
|
def node_coordinates(self):
|
||||||
"""Return initial coordinates of the cell centers."""
|
"""Return initial coordinates of the cell centers."""
|
||||||
if self.structured:
|
if self.structured:
|
||||||
|
@ -561,7 +567,7 @@ class Result:
|
||||||
'Creator': inspect.stack()[0][3][1:]
|
'Creator': inspect.stack()[0][3][1:]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
def add_calculation(self,label,formula,unit='n/a',description=None,vectorized=True):
|
def add_calculation(self,label,formula,unit='n/a',description=None):
|
||||||
"""
|
"""
|
||||||
Add result of a general formula.
|
Add result of a general formula.
|
||||||
|
|
||||||
|
@ -575,13 +581,8 @@ class Result:
|
||||||
Physical unit of the result.
|
Physical unit of the result.
|
||||||
description : str, optional
|
description : str, optional
|
||||||
Human-readable description of the result.
|
Human-readable description of the result.
|
||||||
vectorized : bool, optional
|
|
||||||
Indicate whether the formula can be used in vectorized form. Defaults to ‘True’.
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if not vectorized:
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
dataset_mapping = {d:d for d in set(re.findall(r'#(.*?)#',formula))} # datasets used in the formula
|
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}
|
args = {'formula':formula,'label':label,'unit':unit,'description':description}
|
||||||
self._add_generic_pointwise(self._add_calculation,dataset_mapping,args)
|
self._add_generic_pointwise(self._add_calculation,dataset_mapping,args)
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import copy
|
import copy
|
||||||
import os
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
@ -26,7 +25,7 @@ def default():
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def reference_dir(reference_dir_base):
|
def reference_dir(reference_dir_base):
|
||||||
"""Directory containing reference results."""
|
"""Directory containing reference results."""
|
||||||
return os.path.join(reference_dir_base,'Geom')
|
return reference_dir_base/'Geom'
|
||||||
|
|
||||||
|
|
||||||
class TestGeom:
|
class TestGeom:
|
||||||
|
@ -87,7 +86,7 @@ class TestGeom:
|
||||||
modified = copy.deepcopy(default)
|
modified = copy.deepcopy(default)
|
||||||
modified.mirror(directions,reflect)
|
modified.mirror(directions,reflect)
|
||||||
tag = f'directions={"-".join(directions)}_reflect={reflect}'
|
tag = f'directions={"-".join(directions)}_reflect={reflect}'
|
||||||
reference = os.path.join(reference_dir,f'mirror_{tag}.geom')
|
reference = reference_dir/f'mirror_{tag}.geom'
|
||||||
if update: modified.to_file(reference)
|
if update: modified.to_file(reference)
|
||||||
assert geom_equal(modified,Geom.from_file(reference))
|
assert geom_equal(modified,Geom.from_file(reference))
|
||||||
|
|
||||||
|
@ -96,7 +95,7 @@ class TestGeom:
|
||||||
modified = copy.deepcopy(default)
|
modified = copy.deepcopy(default)
|
||||||
modified.clean(stencil)
|
modified.clean(stencil)
|
||||||
tag = f'stencil={stencil}'
|
tag = f'stencil={stencil}'
|
||||||
reference = os.path.join(reference_dir,f'clean_{tag}.geom')
|
reference = reference_dir/f'clean_{tag}.geom'
|
||||||
if update: modified.to_file(reference)
|
if update: modified.to_file(reference)
|
||||||
assert geom_equal(modified,Geom.from_file(reference))
|
assert geom_equal(modified,Geom.from_file(reference))
|
||||||
|
|
||||||
|
@ -113,7 +112,7 @@ class TestGeom:
|
||||||
modified = copy.deepcopy(default)
|
modified = copy.deepcopy(default)
|
||||||
modified.scale(grid)
|
modified.scale(grid)
|
||||||
tag = f'grid={util.srepr(grid,"-")}'
|
tag = f'grid={util.srepr(grid,"-")}'
|
||||||
reference = os.path.join(reference_dir,f'scale_{tag}.geom')
|
reference = reference_dir/f'scale_{tag}.geom'
|
||||||
if update: modified.to_file(reference)
|
if update: modified.to_file(reference)
|
||||||
assert geom_equal(modified,Geom.from_file(reference))
|
assert geom_equal(modified,Geom.from_file(reference))
|
||||||
|
|
||||||
|
@ -152,7 +151,7 @@ class TestGeom:
|
||||||
modified = copy.deepcopy(default)
|
modified = copy.deepcopy(default)
|
||||||
modified.rotate(Rotation.from_Eulers(Eulers,degrees=True))
|
modified.rotate(Rotation.from_Eulers(Eulers,degrees=True))
|
||||||
tag = f'Eulers={util.srepr(Eulers,"-")}'
|
tag = f'Eulers={util.srepr(Eulers,"-")}'
|
||||||
reference = os.path.join(reference_dir,f'rotate_{tag}.geom')
|
reference = reference_dir/f'rotate_{tag}.geom'
|
||||||
if update: modified.to_file(reference)
|
if update: modified.to_file(reference)
|
||||||
assert geom_equal(modified,Geom.from_file(reference))
|
assert geom_equal(modified,Geom.from_file(reference))
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ def inverse_pole(orientation,axis,proper=False,SST=True):
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def reference_dir(reference_dir_base):
|
def reference_dir(reference_dir_base):
|
||||||
"""Directory containing reference results."""
|
"""Directory containing reference results."""
|
||||||
return os.path.join(reference_dir_base,'Rotation')
|
return reference_dir_base/'Rotation'
|
||||||
|
|
||||||
|
|
||||||
class TestOrientation:
|
class TestOrientation:
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import time
|
import time
|
||||||
import shutil
|
import shutil
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -10,13 +11,14 @@ import h5py
|
||||||
import damask
|
import damask
|
||||||
from damask import Result
|
from damask import Result
|
||||||
from damask import mechanics
|
from damask import mechanics
|
||||||
|
from damask import grid_filters
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def default(tmp_path,reference_dir):
|
def default(tmp_path,reference_dir):
|
||||||
"""Small Result file in temp location for modification."""
|
"""Small Result file in temp location for modification."""
|
||||||
fname = '12grains6x7x8_tensionY.hdf5'
|
fname = '12grains6x7x8_tensionY.hdf5'
|
||||||
shutil.copy(os.path.join(reference_dir,fname),tmp_path)
|
shutil.copy(reference_dir/fname,tmp_path)
|
||||||
f = Result(os.path.join(tmp_path,fname))
|
f = Result(tmp_path/fname)
|
||||||
f.pick('times',20.0)
|
f.pick('times',20.0)
|
||||||
return f
|
return f
|
||||||
|
|
||||||
|
@ -24,13 +26,13 @@ def default(tmp_path,reference_dir):
|
||||||
def single_phase(tmp_path,reference_dir):
|
def single_phase(tmp_path,reference_dir):
|
||||||
"""Single phase Result file in temp location for modification."""
|
"""Single phase Result file in temp location for modification."""
|
||||||
fname = '6grains6x7x8_single_phase_tensionY.hdf5'
|
fname = '6grains6x7x8_single_phase_tensionY.hdf5'
|
||||||
shutil.copy(os.path.join(reference_dir,fname),tmp_path)
|
shutil.copy(reference_dir/fname,tmp_path)
|
||||||
return Result(os.path.join(tmp_path,fname))
|
return Result(tmp_path/fname)
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def reference_dir(reference_dir_base):
|
def reference_dir(reference_dir_base):
|
||||||
"""Directory containing reference results."""
|
"""Directory containing reference results."""
|
||||||
return os.path.join(reference_dir_base,'Result')
|
return reference_dir_base/'Result'
|
||||||
|
|
||||||
|
|
||||||
class TestResult:
|
class TestResult:
|
||||||
|
@ -98,8 +100,19 @@ class TestResult:
|
||||||
in_file = default.read_dataset(loc['|Fe|'],0)
|
in_file = default.read_dataset(loc['|Fe|'],0)
|
||||||
assert np.allclose(in_memory,in_file)
|
assert np.allclose(in_memory,in_file)
|
||||||
|
|
||||||
def test_add_calculation(self,default):
|
@pytest.mark.parametrize('mode',['direct','function'])
|
||||||
default.add_calculation('x','2.0*np.abs(#F#)-1.0','-','my notes')
|
def test_add_calculation(self,default,tmp_path,mode):
|
||||||
|
|
||||||
|
if mode == 'direct':
|
||||||
|
default.add_calculation('x','2.0*np.abs(#F#)-1.0','-','my notes')
|
||||||
|
else:
|
||||||
|
with open(tmp_path/'f.py','w') as f:
|
||||||
|
f.write("import numpy as np\ndef my_func(field):\n return 2.0*np.abs(field)-1.0\n")
|
||||||
|
sys.path.insert(0,str(tmp_path))
|
||||||
|
import f
|
||||||
|
default.enable_user_function(f.my_func)
|
||||||
|
default.add_calculation('x','my_func(#F#)','-','my notes')
|
||||||
|
|
||||||
loc = {'F': default.get_dataset_location('F'),
|
loc = {'F': default.get_dataset_location('F'),
|
||||||
'x': default.get_dataset_location('x')}
|
'x': default.get_dataset_location('x')}
|
||||||
in_memory = 2.0*np.abs(default.read_dataset(loc['F'],0))-1.0
|
in_memory = 2.0*np.abs(default.read_dataset(loc['F'],0))-1.0
|
||||||
|
@ -312,6 +325,16 @@ class TestResult:
|
||||||
with pytest.raises(PermissionError):
|
with pytest.raises(PermissionError):
|
||||||
default.rename('P','another_new_name')
|
default.rename('P','another_new_name')
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('mode',['cell','node'])
|
||||||
|
def test_coordinates(self,default,mode):
|
||||||
|
if mode == 'cell':
|
||||||
|
a = grid_filters.cell_coord0(default.grid,default.size,default.origin)
|
||||||
|
b = default.cell_coordinates.reshape(tuple(default.grid)+(3,),order='F')
|
||||||
|
elif mode == 'node':
|
||||||
|
a = grid_filters.node_coord0(default.grid,default.size,default.origin)
|
||||||
|
b = default.node_coordinates.reshape(tuple(default.grid+1)+(3,),order='F')
|
||||||
|
assert np.allclose(a,b)
|
||||||
|
|
||||||
@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)
|
||||||
|
|
|
@ -6,7 +6,7 @@ import numpy as np
|
||||||
from damask import Rotation
|
from damask import Rotation
|
||||||
from damask import _rotation
|
from damask import _rotation
|
||||||
|
|
||||||
n = 1100
|
n = 1000
|
||||||
atol=1.e-4
|
atol=1.e-4
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import os
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
@ -15,7 +13,7 @@ def default():
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def reference_dir(reference_dir_base):
|
def reference_dir(reference_dir_base):
|
||||||
"""Directory containing reference results."""
|
"""Directory containing reference results."""
|
||||||
return os.path.join(reference_dir_base,'Table')
|
return reference_dir_base/'Table'
|
||||||
|
|
||||||
class TestTable:
|
class TestTable:
|
||||||
|
|
||||||
|
@ -35,9 +33,13 @@ class TestTable:
|
||||||
d = default.get('5_F')
|
d = default.get('5_F')
|
||||||
assert np.allclose(d,1.0) and d.shape[1:] == (1,)
|
assert np.allclose(d,1.0) and d.shape[1:] == (1,)
|
||||||
|
|
||||||
def test_write_read_str(self,default,tmpdir):
|
@pytest.mark.parametrize('mode',['str','path'])
|
||||||
default.to_ASCII(str(tmpdir.join('default.txt')))
|
def test_write_read(self,default,tmpdir,mode):
|
||||||
new = Table.from_ASCII(str(tmpdir.join('default.txt')))
|
default.to_ASCII(tmpdir/'default.txt')
|
||||||
|
if mode == 'path':
|
||||||
|
new = Table.from_ASCII(tmpdir/'default.txt')
|
||||||
|
elif mode == 'str':
|
||||||
|
new = Table.from_ASCII(str(tmpdir/'default.txt'))
|
||||||
assert all(default.data==new.data) and default.shapes == new.shapes
|
assert all(default.data==new.data) and default.shapes == new.shapes
|
||||||
|
|
||||||
def test_write_read_file(self,default,tmpdir):
|
def test_write_read_file(self,default,tmpdir):
|
||||||
|
@ -54,20 +56,25 @@ class TestTable:
|
||||||
new = Table.from_ASCII(f)
|
new = Table.from_ASCII(f)
|
||||||
assert all(default.data==new.data) and default.shapes == new.shapes
|
assert all(default.data==new.data) and default.shapes == new.shapes
|
||||||
|
|
||||||
def test_read_ang_str(self,reference_dir):
|
|
||||||
new = Table.from_ang(os.path.join(reference_dir,'simple.ang'))
|
@pytest.mark.parametrize('mode',['str','path'])
|
||||||
|
def test_read_ang(self,reference_dir,mode):
|
||||||
|
if mode == 'path':
|
||||||
|
new = Table.from_ang(reference_dir/'simple.ang')
|
||||||
|
elif mode == 'str':
|
||||||
|
new = Table.from_ang(str(reference_dir/'simple.ang'))
|
||||||
assert new.data.shape == (4,10) and \
|
assert new.data.shape == (4,10) and \
|
||||||
new.labels == ['eu', 'pos', 'IQ', 'CI', 'ID', 'intensity', 'fit']
|
new.labels == ['eu', 'pos', 'IQ', 'CI', 'ID', 'intensity', 'fit']
|
||||||
|
|
||||||
def test_read_ang_file(self,reference_dir):
|
def test_read_ang_file(self,reference_dir):
|
||||||
f = open(os.path.join(reference_dir,'simple.ang'))
|
f = open(reference_dir/'simple.ang')
|
||||||
new = Table.from_ang(f)
|
new = Table.from_ang(f)
|
||||||
assert new.data.shape == (4,10) and \
|
assert new.data.shape == (4,10) and \
|
||||||
new.labels == ['eu', 'pos', 'IQ', 'CI', 'ID', 'intensity', 'fit']
|
new.labels == ['eu', 'pos', 'IQ', 'CI', 'ID', 'intensity', 'fit']
|
||||||
|
|
||||||
@pytest.mark.parametrize('fname',['datatype-mix.txt','whitespace-mix.txt'])
|
@pytest.mark.parametrize('fname',['datatype-mix.txt','whitespace-mix.txt'])
|
||||||
def test_read_strange(self,reference_dir,fname):
|
def test_read_strange(self,reference_dir,fname):
|
||||||
with open(os.path.join(reference_dir,fname)) as f:
|
with open(reference_dir/fname) as f:
|
||||||
Table.from_ASCII(f)
|
Table.from_ASCII(f)
|
||||||
|
|
||||||
def test_set(self,default):
|
def test_set(self,default):
|
||||||
|
|
Loading…
Reference in New Issue