From 81f00ffa2d5536624ab1c104b51b13a24aa5a8ec Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 15 Jun 2024 09:13:26 +0200 Subject: [PATCH 1/4] more examples in docstrings --- python/damask/_rotation.py | 48 ++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/python/damask/_rotation.py b/python/damask/_rotation.py index 3cb2dd6a0..7eb09a377 100644 --- a/python/damask/_rotation.py +++ b/python/damask/_rotation.py @@ -829,12 +829,20 @@ def from_quaternion(q: Union[Sequence[FloatSequence], np.ndarray], ------- new : damask.Rotation + Examples + -------- + >>> import damask + >>> damask.Rotation.from_quaternion([[1,0,0,0],[0,1,0,0]]) + Quaternions of shape (2,) + [[1. 0. 0. 0.] + [0. 1. 0. 0.]] + """ qu = np.array(q,dtype=float) if qu.shape[:-2:-1] != (4,): raise ValueError(f'invalid shape: {qu.shape}') if abs(P) != 1: raise ValueError('P ∉ {-1,1}') - qu[...,1:4] *= -P + if P == 1: qu[...,1:4] *= -1 if accept_homomorph: qu[qu[...,0]<0.] *= -1. @@ -871,6 +879,12 @@ def from_Euler_angles(phi: np.ndarray, ----- Bunge Euler angles correspond to a rotation axis sequence of z–x'–z''. + Examples + -------- + >>> import damask + >>> damask.Rotation.from_Euler_angles([180,0,0],degrees=True) + Quaternion [0. 0. 0. 1.] + """ eu = np.array(phi,dtype=float) if eu.shape[:-2:-1] != (3,): raise ValueError(f'invalid shape: {eu.shape}') @@ -906,12 +920,20 @@ def from_axis_angle(n_omega: np.ndarray, ------- new : damask.Rotation + Examples + -------- + >>> import damask + >>> damask.Rotation.from_axis_angle([[0,0,1,90],[1,0,0,180]],degrees=True) + Quaternions of shape (2,) + [[0.707 0. 0. 0.707] + [0. 1. 0. 0. ]] + """ ax = np.array(n_omega,dtype=float) if ax.shape[:-2:-1] != (4,): raise ValueError(f'invalid shape: {ax.shape}') if abs(P) != 1: raise ValueError('P ∉ {-1,1}') - ax[...,0:3] *= -P + if P == 1: ax[...,0:3] *= -1 if degrees: ax[..., 3] = np.radians(ax[...,3]) if np.any(ax[...,3] < 0.) or np.any(ax[...,3] > np.pi): with np.printoptions(threshold=sys.maxsize,precision=16,floatmode='fixed'): @@ -985,6 +1007,12 @@ def from_matrix(R: np.ndarray, ------- new : damask.Rotation + Examples + -------- + >>> import damask + >>> damask.Rotation.from_matrix([[1,0,0],[0,0,-1],[0,1,0]]) + Quaternion [ 0.707 -0.707 0. 0. ] + """ return Rotation.from_basis(np.array(R,dtype=float) * (np.linalg.det(R)**(-1./3.))[...,np.newaxis,np.newaxis] if normalize else @@ -1007,6 +1035,12 @@ def from_parallel(a: np.ndarray, ------- new : damask.Rotation + Examples + -------- + >>> import damask + >>> damask.Rotation.from_parallel([[2,0,0],[0,1,0]],[[1,0,0],[0,2,0]]) + Quaternion [1. 0. 0. 0.] + """ a_ = np.array(a,dtype=float) b_ = np.array(b,dtype=float) @@ -1047,12 +1081,18 @@ def from_Rodrigues_vector(rho: np.ndarray, ------- new : damask.Rotation + Examples + -------- + >>> import damask + >>> damask.Rotation.from_Rodrigues_vector([0,0,1,1]) + Quaternion [0.707 0. 0. 0.707] + """ ro = np.array(rho,dtype=float) if ro.shape[:-2:-1] != (4,): raise ValueError(f'invalid shape: {ro}') if abs(P) != 1: raise ValueError('P ∉ {-1,1}') - ro[...,0:3] *= -P + if P == 1: ro[...,0:3] *= -1 if np.any(ro[...,3] < 0.): with np.printoptions(threshold=sys.maxsize,precision=16,floatmode='fixed'): raise ValueError(f'Rodrigues vector rotation angle is negative\n{ro}') @@ -1087,7 +1127,7 @@ def from_homochoric(h: np.ndarray, if ho.shape[:-2:-1] != (3,): raise ValueError(f'invalid shape: {ho.shape}') if abs(P) != 1: raise ValueError('P ∉ {-1,1}') - ho *= -P + if P == 1: ho *= -1 if np.any(np.linalg.norm(ho,axis=-1) > _R1+1.e-9): with np.printoptions(threshold=sys.maxsize,precision=16,floatmode='fixed'): From 12f39137d12a059f49c507417a6041a28729351e Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 16 Jun 2024 09:06:36 +0200 Subject: [PATCH 2/4] example output tested with doctest requires https://github.com/wooyek/pytest-doctest-ellipsis-markers and files from doctest in ressources --- python/damask/_colormap.py | 2 + python/damask/_configmaterial.py | 183 +++++++++++------- python/damask/_geomgrid.py | 21 +- python/damask/_orientation.py | 33 ++-- python/damask/_result.py | 41 ++-- python/damask/_rotation.py | 28 +-- python/damask/seeds.py | 4 +- python/damask/util.py | 28 +-- python/pyproject.toml | 3 + python/tests/resources/doctest/material.yaml | 26 +++ python/tests/resources/doctest/n20-id1.vtk | Bin 0 -> 65807 bytes python/tests/resources/doctest/small.txt | 4 + python/tests/resources/doctest/tensionX.yaml | 18 ++ python/tests/resources/doctest/two_phase.vti | 19 ++ .../doctest/two_phase_tensionX_material.hdf5 | Bin 0 -> 176361 bytes 15 files changed, 270 insertions(+), 140 deletions(-) create mode 100644 python/tests/resources/doctest/material.yaml create mode 100644 python/tests/resources/doctest/n20-id1.vtk create mode 100644 python/tests/resources/doctest/small.txt create mode 100644 python/tests/resources/doctest/tensionX.yaml create mode 100644 python/tests/resources/doctest/two_phase.vti create mode 100644 python/tests/resources/doctest/two_phase_tensionX_material.hdf5 diff --git a/python/damask/_colormap.py b/python/damask/_colormap.py index a40cebf4d..cb0251a41 100644 --- a/python/damask/_colormap.py +++ b/python/damask/_colormap.py @@ -185,6 +185,7 @@ def from_range(low: FloatSequence, -------- >>> import damask >>> damask.Colormap.from_range((0,0,1),(0,0,0),'blue_to_black') + Colormap: blue_to_black """ toMsh = dict( @@ -248,6 +249,7 @@ def from_predefined(name: str, -------- >>> import damask >>> damask.Colormap.from_predefined('strain') + Colormap: strain """ if name in cm.__dict__: diff --git a/python/damask/_configmaterial.py b/python/damask/_configmaterial.py index 81c78553d..491f99463 100644 --- a/python/damask/_configmaterial.py +++ b/python/damask/_configmaterial.py @@ -197,42 +197,43 @@ def from_table(table: Table,*, Examples -------- >>> import damask - >>> import damask.ConfigMaterial as cm + >>> from damask import ConfigMaterial as cm >>> t = damask.Table.load('small.txt') >>> t - 3:pos pos pos 4: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 - 2 1 1 0 0.8 0.19 0.24 -0.51 Steel SX + 3:pos pos pos 4:qu qu qu qu phase homog + 0 0 0 0 1.0 0.0 0.0 0.0 Aluminum SX + 1 1 0 0 0.0 1.0 0.0 0.0 Steel SX + 2 1 1 0 0.0 1.0 0.0 0.0 Steel SX + >>> cm.from_table(t,O='qu',phase='phase',homogenization='homog') - material: - - constituents: - - O: [0.19, 0.8, 0.24, -0.51] - v: 1.0 - phase: Aluminum - homogenization: SX - - constituents: - - O: [0.8, 0.19, 0.24, -0.51] - v: 1.0 - phase: Steel - homogenization: SX homogenization: {SX: null} phase: {Aluminum: null, Steel: null} + material: + - constituents: + - phase: Aluminum + O: [1.0, 0.0, 0.0, 0.0] + v: 1.0 + homogenization: SX + - constituents: + - phase: Steel + O: [0.0, 1.0, 0.0, 0.0] + v: 1.0 + homogenization: SX >>> cm.from_table(t,O='qu',phase='phase',homogenization='single_crystal') - material: - - constituents: - - O: [0.19, 0.8, 0.24, -0.51] - v: 1.0 - phase: Aluminum - homogenization: single_crystal - - constituents: - - O: [0.8, 0.19, 0.24, -0.51] - v: 1.0 - phase: Steel - homogenization: single_crystal homogenization: {single_crystal: null} phase: {Aluminum: null, Steel: null} + material: + - constituents: + - phase: Aluminum + O: [1.0, 0.0, 0.0, 0.0] + v: 1.0 + homogenization: single_crystal + - constituents: + - phase: Steel + O: [0.0, 1.0, 0.0, 0.0] + v: 1.0 + homogenization: single_crystal """ kwargs = {} @@ -463,74 +464,112 @@ def material_add(self,*, >>> import damask >>> m = damask.ConfigMaterial() >>> m = m.material_add(phase = ['Ferrite','Martensite','Ferrite'], - ... O = damask.Rotation.from_random(3), + ... O = damask.Rotation.from_random(3,rng_seed=20191102), ... homogenization = 'SX') >>> m + homogenization: {SX: null} + phase: {Ferrite: null, Martensite: null} material: - constituents: - - O: [0.577764, -0.146299, -0.617669, 0.513010] + - phase: Ferrite + O: [0.0047, -0.9582, 0.1084, 0.2645] v: 1.0 - phase: Ferrite homogenization: SX - constituents: - - O: [0.184176, 0.340305, 0.737247, 0.553840] + - phase: Martensite + O: [0.9147, -0.1907, 0.2901, -0.2068] v: 1.0 - phase: Martensite homogenization: SX - constituents: - - O: [0.47925185, -0.04294454, 0.78760173, -0.3849116 ] + - phase: Ferrite + O: [0.1068, -0.4427, 0.1369, 0.8797] v: 1.0 - phase: Ferrite homogenization: SX - homogenization: {SX: null} - phase: {Ferrite: null, Martensite: null} - Create hundred materials that each approximate a duplex stainless steel microstructure + Create three materials that each approximate a duplex stainless steel microstructure with three austenite and one relatively bigger ferrite grain of random orientation each: + >>> import numpy as np >>> import damask >>> m = damask.ConfigMaterial() >>> m = m.material_add(phase = np.array(['Austenite']*3+['Ferrite']), - ... O = damask.Rotation.from_random((100,4)), + ... O = damask.Rotation.from_random((5,4),rng_seed=20191102), ... v = np.array([0.2]*3+[0.4]), ... homogenization = 'Taylor') >>> m - material: - - constituents: - - v: 0.2 - phase: Austenite - O: [0.46183665006602664, 0.2215160420973196, -0.5594313187331139, 0.6516702781083836] - - v: 0.2 - phase: Austenite - O: [0.11321658382410027, 0.6354079414360444, 0.00562701344273936, 0.7638108992590535] - - v: 0.2 - phase: Austenite - O: [0.050991978809077604, 0.8069522034362003, -0.11352928955610851, -0.5773552285027659] - - v: 0.4 - phase: Ferrite - O: [0.9460076150721788, 0.15880754622367604, -0.0069841062241482385, -0.28249066842661014] - homogenization: Taylor - . - . - . - - constituents: - - v: 0.2 - phase: Austenite - O: [0.12531400788494199, -0.18637769037997565, 0.31737548053338394, -0.9213210951197429] - - v: 0.2 - phase: Austenite - O: [0.37453930577161404, -0.33529507696450805, -0.3266564259130028, -0.800370601162502] - - v: 0.2 - phase: Austenite - O: [0.035776891752713764, -0.720706371010592, -0.4540438656728926, -0.5226342017569017] - - v: 0.4 - phase: Ferrite - O: [0.6782596727966124, -0.20800082041703685, -0.138636083554039, 0.6909989227925536] - homogenization: Taylor - homogenization: {Taylor: null} - phase: {Austenite: null, Ferrite: null} + material: + - constituents: + - phase: Austenite + v: 0.2 + O: [0.004702411137213036, -0.9582446864633862, 0.1084379916089085, 0.2645490694937509] + - phase: Austenite + v: 0.2 + O: [0.9147097460704486, -0.19068436891182194, 0.29014401444532145, -0.20678975501215882] + - phase: Austenite + v: 0.2 + O: [0.10677819003833185, -0.4427133706883004, 0.13690394495734726, 0.879693468999888] + - phase: Ferrite + v: 0.4 + O: [0.8664338002923555, 0.04448357787828491, -0.4945927532088464, 0.05188149461403649] + homogenization: Taylor + - constituents: + - phase: Austenite + v: 0.2 + O: [0.5621873738314133, 0.0028841916095125584, -0.817023371343172, -0.1281009321680984] + - phase: Austenite + v: 0.2 + O: [0.1566777437467901, -0.8117282158019414, 0.5096142534839398, 0.23841707348975383] + - phase: Austenite + v: 0.2 + O: [0.3559036203819333, 0.1946923701552408, 0.058744995087853975, -0.9121274689178566] + - phase: Ferrite + v: 0.4 + O: [0.467387781713959, -0.35644325887489176, 0.8031986430613528, 0.09679258489963502] + homogenization: Taylor + - constituents: + - phase: Austenite + v: 0.2 + O: [0.4399087544327661, 0.12802483830067418, -0.8257167208737983, 0.32906203886337354] + - phase: Austenite + v: 0.2 + O: [0.12410381094181624, -0.5125024631828828, -0.8493860709598213, 0.021972068647108236] + - phase: Austenite + v: 0.2 + O: [0.03909373022192218, 0.4596226773046959, 0.42809626138739537, 0.7771436583738773] + - phase: Ferrite + v: 0.4 + O: [0.737821660605232, 0.38809925187040367, -0.012129167758963711, 0.5521331824196455] + homogenization: Taylor + - constituents: + - phase: Austenite + v: 0.2 + O: [0.4924738838478857, -0.0534798919571679, -0.6570981342247908, 0.5681825559468784] + - phase: Austenite + v: 0.2 + O: [0.13073521303792138, 0.2534173177988532, -0.9582490914178947, -0.021133998872519554] + - phase: Austenite + v: 0.2 + O: [0.1633346595899539, 0.6775968809652247, -0.07127256805012916, -0.71351557581203] + - phase: Ferrite + v: 0.4 + O: [0.7658044627436773, -0.5327872540278646, 0.1102330397070761, 0.34282640467772235] + homogenization: Taylor + - constituents: + - phase: Austenite + v: 0.2 + O: [0.25814496892598815, -0.6159961898524933, -0.5080223627084379, 0.543896265930874] + - phase: Austenite + v: 0.2 + O: [0.8497433829153472, 0.4264182767672584, 0.05570674517418605, -0.3049596612218108] + - phase: Austenite + v: 0.2 + O: [0.5146112784760113, 0.529467219604771, 0.661078636611197, 0.13347183839881469] + - phase: Ferrite + v: 0.4 + O: [0.18430893147208752, 0.012407731059331692, -0.5551804816056372, -0.8109567798802285] + homogenization: Taylor """ dim = {'O':(4,),'V_e':(3,3,)} diff --git a/python/damask/_geomgrid.py b/python/damask/_geomgrid.py index a996acc7b..ca232275b 100644 --- a/python/damask/_geomgrid.py +++ b/python/damask/_geomgrid.py @@ -377,6 +377,7 @@ def load_Neper(fname: Union[str, Path]) -> 'GeomGrid': >>> N_grains = 20 >>> cells = (32,32,32) >>> damask.util.run(f'neper -T -n {N_grains} -tesrsize {cells[0]}:{cells[1]}:{cells[2]} -periodicity all -format vtk') + running 'neper -T -n 20 -tesrsize 32:32:32 -periodicity all -format vtk' ... >>> damask.GeomGrid.load_Neper(f'n{N_grains}-id1.vtk').renumber() cells: 32 × 32 × 32 size: 1.0 × 1.0 × 1.0 m³ @@ -736,8 +737,8 @@ def from_minimal_surface(cells: IntSequence, >>> import numpy as np >>> import damask >>> damask.GeomGrid.from_minimal_surface([64]*3,np.ones(3)*1.e-4,'Gyroid') - cells : 64 × 64 × 64 - size : 0.0001 × 0.0001 × 0.0001 m³ + cells: 64 × 64 × 64 + size: 0.0001 × 0.0001 × 0.0001 m³ origin: 0.0 0.0 0.0 m # materials: 2 @@ -747,8 +748,8 @@ def from_minimal_surface(cells: IntSequence, >>> import damask >>> damask.GeomGrid.from_minimal_surface([80]*3,np.ones(3)*5.e-4, ... 'Neovius',materials=(1,5)) - cells : 80 × 80 × 80 - size : 0.0005 × 0.0005 × 0.0005 m³ + cells: 80 × 80 × 80 + size: 0.0005 × 0.0005 × 0.0005 m³ origin: 0.0 0.0 0.0 m # materials: 2 (min: 1, max: 5) @@ -1087,8 +1088,8 @@ def scale(self, origin: 0.0 0.0 0.0 m # materials: 1 >>> g.scale(g.cells*2) - cells : 64 × 64 × 64 - size : 0.0001 × 0.0001 × 0.0001 m³ + cells: 64 × 64 × 64 + size: 0.0001 × 0.0001 × 0.0001 m³ origin: 0.0 0.0 0.0 m # materials: 1 @@ -1328,8 +1329,8 @@ def add_primitive(self, >>> import damask >>> g = damask.GeomGrid(np.zeros([64]*3,int), np.ones(3)*1e-4) >>> g.add_primitive(np.ones(3)*5e-5,np.ones(3)*5e-5,1) - cells : 64 × 64 × 64 - size : 0.0001 × 0.0001 × 0.0001 m³ + cells: 64 × 64 × 64 + size: 0.0001 × 0.0001 × 0.0001 m³ origin: 0.0 0.0 0.0 m # materials: 2 @@ -1339,8 +1340,8 @@ def add_primitive(self, >>> import damask >>> g = damask.GeomGrid(np.zeros([64]*3,int), np.ones(3)*1e-4) >>> g.add_primitive(np.ones(3,int)*32,np.zeros(3),np.inf) - cells : 64 × 64 × 64 - size : 0.0001 × 0.0001 × 0.0001 m³ + cells: 64 × 64 × 64 + size: 0.0001 × 0.0001 × 0.0001 m³ origin: 0.0 0.0 0.0 m # materials: 2 diff --git a/python/damask/_orientation.py b/python/damask/_orientation.py index f9daf4ba3..75650dfb6 100644 --- a/python/damask/_orientation.py +++ b/python/damask/_orientation.py @@ -500,13 +500,8 @@ def disorientation(self, >>> a = damask.Orientation.from_Euler_angles(phi=[123,32,21],degrees=True,family='hexagonal') >>> b = damask.Orientation.from_Euler_angles(phi=[104,11,87],degrees=True,family='hexagonal') >>> a.disorientation(b) - Crystal family hexagonal - Quaternion: (real=0.976, imag=<+0.189, +0.018, +0.103>) - Matrix: - [[ 0.97831006 0.20710935 0.00389135] - [-0.19363288 0.90765544 0.37238141] - [ 0.07359167 -0.36505797 0.92807163]] - Bunge Eulers / deg: (11.40, 21.86, 0.60) + Crystal family: hexagonal + Quaternion [0.976 0.189 0.018 0.103] Plot a sample from the Mackenzie distribution. @@ -517,6 +512,7 @@ def disorientation(self, >>> b = damask.Orientation.from_random(shape=N,family='cubic') >>> n,omega = a.disorientation(b).as_axis_angle(degrees=True,pair=True) >>> plt.hist(omega,25) + [...] >>> plt.show() """ @@ -732,7 +728,9 @@ def IPF_color(self, >>> coord = damask.util.project_equal_area(o.to_SST(lab)) >>> color = o.IPF_color(lab) >>> plt.scatter(coord[:,0],coord[:,1],color=color,s=.06) + [...] >>> plt.axis('scaled') + [...] >>> plt.show() """ @@ -798,16 +796,15 @@ def to_lattice(self, *, Examples -------- - >>> import np + >>> import numpy as np >>> import damask - >>> np.set_printoptions(precision=2,suppress=True,floatmode='maxprec') >>> cubic = damask.Orientation.from_axis_angle(n_omega=[1,0,0,90],degrees=True,lattice='cI') >>> cubic.to_lattice(direction=[1, 0, 0]) array([1., 0., 0.]) >>> cubic.to_lattice(direction=[0, 1, 0]) - array([ 0., 0., -1.]) + array([0., 0., -1.]) >>> cubic.to_lattice(direction=[0, 0, 1]) - array([-0., 1., 0.]) + array([-0., 1., 0.]) >>> tetragonal = damask.Orientation(lattice='tI',c=0.5) >>> damask.util.scale_to_coprime(tetragonal.to_lattice(direction=[1,1,1])) array([1, 1, 2]) @@ -891,7 +888,6 @@ def Schmid(self, *, >>> import numpy as np >>> import damask - >>> np.set_printoptions(3,suppress=True,floatmode='fixed') >>> O = damask.Orientation.from_Euler_angles(phi=[0,45,0],degrees=True,lattice='cF') >>> O.Schmid(N_slip=[12])[0] array([[ 0.000, 0.000, 0.000], @@ -944,20 +940,19 @@ def related(self: MyType, -------- Face-centered cubic orientations following from a body-centered cubic crystal in "Cube" orientation according - to the Bain orientation relationship (cI -> cF). + to the Bain orientation relationship (cF -> cI). >>> import numpy as np >>> import damask - >>> np.set_printoptions(3,suppress=True,floatmode='fixed') - >>> damask.Orientation(lattice='cI').related('Bain') + >>> damask.Orientation(lattice='cF').related('Bain') Crystal family: cubic - Bravais lattice: cF + Bravais lattice: cI a=1 m, b=1 m, c=1 m α=90°, β=90°, γ=90° Quaternions of shape (3,) - [[0.924 0.383 0.000 0.000] - [0.924 0.000 0.383 0.000] - [0.924 0.000 0.000 0.383]] + [[ 6.53281482e-01 2.70598050e-01 6.53281482e-01 2.70598050e-01] + [ 2.70598050e-01 -2.70598050e-01 -6.53281482e-01 -6.53281482e-01] + [ 9.23879533e-01 -5.55111512e-17 -2.77555756e-17 -3.82683432e-01]] """ lattice,o = self.relation_operations(model,target) diff --git a/python/damask/_result.py b/python/damask/_result.py index f977a8eb5..cdd09b7a2 100644 --- a/python/damask/_result.py +++ b/python/damask/_result.py @@ -64,7 +64,7 @@ def _empty_like(dataset: np.ma.core.MaskedArray, class Result: - """ + r""" Add data to and export data from a DADF5 (DAMASK HDF5) file. A DADF5 file contains DAMASK results. @@ -83,11 +83,11 @@ class Result: >>> import damask >>> r = damask.Result('my_file.hdf5') - >>> r.add_stress_Cauchy() - >>> r.add_equivalent_Mises('sigma') - >>> r.export_VTK() - >>> r_last = r.view(increments=-1) - >>> sigma_vM_last = r_last.get('sigma_vM') + >>> r + \x1b[2mCreated by DAMASK_grid ... + on ... + executing "..."\x1b[0m + ... """ @@ -394,7 +394,7 @@ def view_more(self,*, >>> import damask >>> r_empty = damask.Result('my_file.hdf5').view(increments=False) >>> r_first = r_empty.view_more(increments=0) - >>> r_first_and_last = r.first.view_more(increments=-1) + >>> r_first_and_last = r_first.view_more(increments=-1) """ return self._manage_view('add',increments,times,phases,homogenizations,fields) @@ -458,7 +458,7 @@ def view_all(self): def rename(self, name_src: str, name_dst: str): - """ + r""" Rename/move datasets (within the same group/folder). This operation is discouraged because the history of the @@ -478,6 +478,7 @@ def rename(self, >>> import damask >>> r = damask.Result('my_file.hdf5') >>> r_unprotected = r.view(protected=False) + \x1b[93m\x1b[1mWarning: Modification of existing datasets allowed!\x1b[0m\x1b[0m >>> r_unprotected.rename('F','def_grad') """ @@ -499,7 +500,7 @@ def rename(self, def remove(self, name: str): - """ + r""" Remove/delete datasets. This operation is discouraged because the history of the @@ -517,6 +518,7 @@ def remove(self, name: str): >>> import damask >>> r = damask.Result('my_file.hdf5') >>> r_unprotected = r.view(protected=False) + \x1b[93m\x1b[1mWarning: Modification of existing datasets allowed!\x1b[0m\x1b[0m >>> r_unprotected.remove('F') """ @@ -687,10 +689,13 @@ def add_calculation(self, >>> r = damask.Result('my_file.hdf5') >>> r.add_calculation('np.sum(#rho_mob#,axis=1)','rho_mob_total', ... '1/m²','total mobile dislocation density') + [...] >>> r.add_calculation('np.sum(#rho_dip#,axis=1)','rho_dip_total', ... '1/m²','total dislocation dipole density') + [...] >>> r.add_calculation('#rho_dip_total#+#rho_mob_total#','rho_total', ... '1/m²','total dislocation density') + [...] Add Mises equivalent of the Cauchy stress without storage of intermediate results. Define a user function for better readability: @@ -701,8 +706,10 @@ def add_calculation(self, ... return damask.mechanics.equivalent_stress_Mises(sigma) >>> r = damask.Result('my_file.hdf5') >>> r.enable_user_function(equivalent_stress) + Function equivalent_stress enabled in add_calculation. >>> r.add_calculation('equivalent_stress(#F#,#P#)','sigma_vM','Pa', ... 'Mises equivalent of the Cauchy stress') + [...] """ def calculation(**kwargs) -> DADF5Dataset: @@ -778,6 +785,7 @@ def add_determinant(self, T: str): >>> import damask >>> r = damask.Result('my_file.hdf5') >>> r.add_determinant('F_p') + [...] """ @@ -811,6 +819,7 @@ def add_deviator(self, T: str): >>> import damask >>> r = damask.Result('my_file.hdf5') >>> r.add_deviator('sigma') + [...] """ @@ -848,6 +857,7 @@ def add_eigenvalue(self, >>> import damask >>> r = damask.Result('my_file.hdf5') >>> r.add_eigenvalue('sigma','min') + [...] """ @@ -922,7 +932,7 @@ def add_IPF_color(self, Parameters ---------- - l : numpy.array of shape (3) + l : numpy.array of shape (3) or compatible Lab frame direction for inverse pole figure. q : str, optional Name of the dataset containing the crystallographic orientation as quaternions. @@ -934,7 +944,8 @@ def add_IPF_color(self, >>> import damask >>> r = damask.Result('my_file.hdf5') - >>> r.add_IPF_color(np.array([0,1,1])) + >>> r.add_IPF_color(l = [0,1,1], q = 'O') + [...] """ @@ -1002,12 +1013,14 @@ def add_equivalent_Mises(self, >>> import damask >>> r = damask.Result('my_file.hdf5') >>> r.add_equivalent_Mises('sigma') + [...] Add the Mises equivalent of the spatial logarithmic strain 'epsilon_V^0.0(F)': >>> import damask >>> r = damask.Result('my_file.hdf5') >>> r.add_equivalent_Mises('epsilon_V^0.0(F)') + [...] """ def equivalent_Mises(T_sym: DADF5Dataset, kind: str) -> DADF5Dataset: @@ -1128,7 +1141,7 @@ def add_pole(self, q : str, optional Name of the dataset containing the crystallographic orientation as quaternions. Defaults to 'O'. - uvw|hkl : numpy.ndarray of shape (3) + uvw|hkl : numpy.ndarray of shape (3) or compatible Miller indices of crystallographic direction or plane normal. with_symmetry : bool, optional Calculate all N symmetrically equivalent vectors. @@ -1182,6 +1195,7 @@ def add_rotation(self, F: str): >>> import damask >>> r = damask.Result('my_file.hdf5') >>> r.add_rotation('F') + [...] """ def rotation(F: DADF5Dataset) -> DADF5Dataset: @@ -1214,6 +1228,7 @@ def add_spherical(self, T: str): >>> import damask >>> r = damask.Result('my_file.hdf5') >>> r.add_spherical('sigma') + [...] """ def spherical(T: DADF5Dataset) -> DADF5Dataset: @@ -1257,12 +1272,14 @@ def add_strain(self, >>> import damask >>> r = damask.Result('my_file.hdf5') >>> r.add_strain(t='V',m=-1.0) + [...] Add the plastic Biot strain: >>> import damask >>> r = damask.Result('my_file.hdf5') >>> r.add_strain('F_p','U',0.5) + [...] Notes ----- diff --git a/python/damask/_rotation.py b/python/damask/_rotation.py index 7eb09a377..f2290496d 100644 --- a/python/damask/_rotation.py +++ b/python/damask/_rotation.py @@ -402,44 +402,50 @@ def __matmul__(self, Examples -------- - All below examples rely on imported modules: - >>> import numpy as np - >>> import damask - Application of twelve (random) rotations to a set of five vectors. + >>> import numpy as np + >>> import damask >>> r = damask.Rotation.from_random(shape=(12)) >>> o = np.ones((5,3)) >>> (r@o).shape # (12) @ (5, 3) - (12,5, 3) + (12, 5, 3) Application of a (random) rotation to all twelve second-rank tensors. + >>> import numpy as np + >>> import damask >>> r = damask.Rotation.from_random() >>> o = np.ones((12,3,3)) >>> (r@o).shape # (1) @ (12, 3,3) - (12,3,3) + (12, 3, 3) Application of twelve (random) rotations to the corresponding twelve second-rank tensors. + >>> import numpy as np + >>> import damask >>> r = damask.Rotation.from_random(shape=(12)) >>> o = np.ones((12,3,3)) >>> (r@o).shape # (12) @ (3,3) - (12,3,3) + (12, 3, 3) Application of each of three (random) rotations to all three vectors. + >>> import numpy as np + >>> import damask >>> r = damask.Rotation.from_random(shape=(3)) >>> o = np.ones((3,3)) >>> (r[...,np.newaxis]@o[np.newaxis,...]).shape # (3,1) @ (1,3, 3) - (3,3,3) + (3, 3, 3) Application of twelve (random) rotations to all twelve second-rank tensors. + >>> import numpy as np + >>> import damask >>> r = damask.Rotation.from_random(shape=(12)) >>> o = np.ones((12,3,3)) >>> (r@o[np.newaxis,...]).shape # (12) @ (1,12, 3,3) - (12,3,3,3) + (12, 12, 3, 3) """ if isinstance(other, np.ndarray): @@ -923,10 +929,10 @@ def from_axis_angle(n_omega: np.ndarray, Examples -------- >>> import damask - >>> damask.Rotation.from_axis_angle([[0,0,1,90],[1,0,0,180]],degrees=True) + >>> damask.Rotation.from_axis_angle([[0,0,1,90],[1,0,0,90]],degrees=True) Quaternions of shape (2,) [[0.707 0. 0. 0.707] - [0. 1. 0. 0. ]] + [0.707 0.707 0. 0. ]] """ ax = np.array(n_omega,dtype=float) diff --git a/python/damask/seeds.py b/python/damask/seeds.py index 85c157ece..23468df7d 100644 --- a/python/damask/seeds.py +++ b/python/damask/seeds.py @@ -147,7 +147,7 @@ def from_grid(grid, >>> import numpy as np >>> import scipy.spatial >>> import damask - >>> seeds = damask.seeds.from_random(np.ones(3),29,[128]*3) + >>> seeds = damask.seeds.from_random(np.ones(3),29,[128]*3,rng_seed=20191102) >>> (g := damask.GeomGrid.from_Voronoi_tessellation([128]*3,np.ones(3),seeds)) cells: 128 × 128 × 128 size: 1.0 × 1.0 × 1.0 m³ @@ -156,7 +156,7 @@ def from_grid(grid, >>> COG,matID = damask.seeds.from_grid(g,average=True) >>> distance,ID = scipy.spatial.KDTree(COG,boxsize=g.size).query(seeds) >>> np.max(distance) / np.linalg.norm(g.size/g.cells) - 7.8057356746350415 + 10.1 >>> (ID == matID).all() True diff --git a/python/damask/util.py b/python/damask/util.py index dd11e3411..0b3f94a9d 100644 --- a/python/damask/util.py +++ b/python/damask/util.py @@ -369,11 +369,11 @@ def project_equal_angle(vector: _np.ndarray, >>> import damask >>> import numpy as np >>> project_equal_angle(np.ones(3)) - [0.3660254, 0.3660254] + array([0.3660, 0.3660]) >>> project_equal_angle(np.ones(3),direction='x',normalize=False,keepdims=True) - [0, 0.5, 0.5] + array([0. , 0.5, 0.5]) >>> project_equal_angle([0,1,1],direction='y',normalize=True,keepdims=False) - [0.41421356, 0] + array([0.4142, 0. ]) """ shift = 'zyx'.index(direction) @@ -418,11 +418,11 @@ def project_equal_area(vector: _np.ndarray, >>> import damask >>> import numpy as np >>> project_equal_area(np.ones(3)) - [0.45970084, 0.45970084] + array([0.4597, 0.4597]) >>> project_equal_area(np.ones(3),direction='x',normalize=False,keepdims=True) - [0.0, 0.70710678, 0.70710678] + array([0. , 0.7071, 0.7071]) >>> project_equal_area([0,1,1],direction='y',normalize=True,keepdims=False) - [0.5411961, 0.0] + array([0.5412, 0. ]) """ shift = 'zyx'.index(direction) @@ -503,7 +503,7 @@ def shapeshifter(fro: _Tuple[int, ...], >>> b = np.ones(4) >>> b_extended = b.reshape(util.shapeshifter(b.shape,a.shape)) >>> (a * np.broadcast_to(b_extended,a.shape)).shape - (3,4,2) + (3, 4, 2) """ if len(fro) == 0 and len(to) == 0: return tuple() @@ -545,19 +545,19 @@ def shapeblender(a: _Tuple[int, ...], Examples -------- >>> shapeblender((3,2),(3,2)) - (3,2) + (3, 2) >>> shapeblender((4,3),(3,2)) - (4,3,2) + (4, 3, 2) >>> shapeblender((4,4),(3,2)) - (4,4,3,2) + (4, 4, 3, 2) >>> shapeblender((1,2),(1,2,3)) - (1,2,3) + (1, 2, 3) >>> shapeblender((),(2,2,1)) - (2,2,1) + (2, 2, 1) >>> shapeblender((1,),(2,2,1)) - (2,2,1) + (2, 2, 1) >>> shapeblender((1,),(2,2,1),True) - (1,2,2,1) + (1, 2, 2, 1) """ def is_broadcastable(a,b): diff --git a/python/pyproject.toml b/python/pyproject.toml index 7ce9bbeb8..4ecafbba6 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -1,3 +1,6 @@ [build-system] requires = ['setuptools >= 40.6.0', 'wheel'] build-backend = 'setuptools.build_meta' + +[tool.pytest.ini_options] +doctest_optionflags = 'NUMBER NORMALIZE_WHITESPACE ELLIPSIS' diff --git a/python/tests/resources/doctest/material.yaml b/python/tests/resources/doctest/material.yaml new file mode 100644 index 000000000..9f29a927a --- /dev/null +++ b/python/tests/resources/doctest/material.yaml @@ -0,0 +1,26 @@ +homogenization: + SX: + N_constituents: 1 + mechanical: {type: pass} + +material: + - constituents: + - v: 1.0 + O: [0.7936696712125002, -0.28765777461664166, -0.3436487135089419, 0.4113964260949434] + phase: phase_A + homogenization: SX + - constituents: + - v: 1.0 + O: [0.7936696712125002, -0.28765777461664166, -0.3436487135089419, 0.4113964260949434] + phase: phase_B + homogenization: SX + +phase: + phase_A: + lattice: cF + mechanical: + elastic: {C_11: 246.5e9, C_12: 147.3e9, C_44: 124.7e9, type: Hooke} + phase_B: + lattice: cF + mechanical: + elastic: {C_11: 246.5e9, C_12: 147.3e9, C_44: 124.7e9, type: Hooke} diff --git a/python/tests/resources/doctest/n20-id1.vtk b/python/tests/resources/doctest/n20-id1.vtk new file mode 100644 index 0000000000000000000000000000000000000000..81ef3b02b80fa94a22f13174ea2dc6bf943fd774 GIT binary patch literal 65807 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 + + + + + AAAAAACAAAAAAAAA + + + + + + + + AQAAAACAAAAAAgAAFgAAAA==eF5jZIAARgbsgBGNHpUfXvIAI4AAIQ== + + + + + diff --git a/python/tests/resources/doctest/two_phase_tensionX_material.hdf5 b/python/tests/resources/doctest/two_phase_tensionX_material.hdf5 new file mode 100644 index 0000000000000000000000000000000000000000..ec82c8d4c68efb17488b5580e507aa154286099a GIT binary patch literal 176361 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 Date: Mon, 17 Jun 2024 16:51:21 +0200 Subject: [PATCH 3/4] vtk files might contain binary data (and no EOL) --- .gitattributes | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitattributes b/.gitattributes index 66063d773..411f03e5e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -10,6 +10,7 @@ *.pdf binary *.dream3d binary *.pbz2 binary +*.vtk binary # ignore files from MSC.Marc in language statistics install/MarcMentat/** linguist-vendored From 60389f3f75f24a782fec7a92433cb4e5e1558702 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 17 Jun 2024 23:24:24 +0200 Subject: [PATCH 4/4] logical array shapes this enables broadcasing for arbitrary N_materials --- python/damask/_configmaterial.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/python/damask/_configmaterial.py b/python/damask/_configmaterial.py index 491f99463..2837d3f93 100644 --- a/python/damask/_configmaterial.py +++ b/python/damask/_configmaterial.py @@ -486,15 +486,16 @@ def material_add(self,*, v: 1.0 homogenization: SX - Create three materials that each approximate a duplex stainless steel microstructure + Create five materials that each approximate a duplex stainless steel microstructure with three austenite and one relatively bigger ferrite grain of random orientation each: >>> import numpy as np >>> import damask >>> m = damask.ConfigMaterial() - >>> m = m.material_add(phase = np.array(['Austenite']*3+['Ferrite']), - ... O = damask.Rotation.from_random((5,4),rng_seed=20191102), - ... v = np.array([0.2]*3+[0.4]), + >>> N_materials = 5 + >>> m = m.material_add(phase = np.array([['Austenite']*3+['Ferrite']]), + ... O = damask.Rotation.from_random((N_materials,4),rng_seed=20191102), + ... v = np.array([[0.2]*3+[0.4]]), ... homogenization = 'Taylor') >>> m homogenization: {Taylor: null}