Skip to content

Commit dc5b36b

Browse files
committed
Add new capabilities
- general: switched "active" and "passive" for orientation convention (see incompatibility note below), changed convention for HCP directions. - module -T: added -format svg, added -n ... -morpho lamellae and (the equivalent) -morpho lamellar(n=...)", fixed regularization in the case of curved domain edges, improved -domain and -loadtess to load CAD files (tess, obj, ovm), added tessellation key length(d_x,d_y,d_z). - module -M: improved meshing of 2D tessellations with curved domain edges, made minor bug fixes and improvements. - module -S: made minor bug fixes.
1 parent 4ce18e4 commit dc5b36b

File tree

1,625 files changed

+15531
-7284
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,625 files changed

+15531
-7284
lines changed

VERSIONS

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,25 @@
1-
New in 4.9.1-6 (16 Sep 2024):
2-
- module -T: added -n ... -morpho lamellae and (the equivalent)
3-
-morpho lamellar(n=...)", made minor fix to regularization of
4-
2D cut domain, added tessellation key length(d_x,dd_y,d_z).
5-
- made minor fixes and improvements.
1+
New in 4.10.0 (01 Oct 2024):
2+
- general: switched "active" and "passive" for orientation convention (see
3+
incompatibility note below), changed convention for HCP directions.
4+
- module -T: added -format svg, added -n ... -morpho lamellae and (the
5+
equivalent) -morpho lamellar(n=...)", fixed regularization in the case of
6+
curved domain edges, improved -domain and -loadtess to load CAD files (tess,
7+
obj, ovm), added tessellation key length(d_x,d_y,d_z).
8+
- module -M: improved meshing of 2D tessellations with curved domain edges,
9+
made minor bug fixes and improvements.
10+
- module -S: made minor bug fixes.
11+
12+
* Incompatible changes in -T:
13+
- switched "active" and "passive" for orientation convention. The default
14+
convention is now "passive". The orientation data themselves remain the
15+
same. Bumped version numbers to 3.5 for tess, 2.2 for tesr, 2.3 for msh
16+
and 1.1 for sim. When an older tess, tesr, msh or sim is parsed, the
17+
defined convention is changed from active to passive and vice versa. This
18+
ensures no change in Neper's own behavior. Postprocessors that are
19+
sensitive to the change of convention should be updated accordingly.
20+
- changed convention for HCP directions (see the documentation).
21+
- changed -domain "cell(<tess_file>,<cell_id>)" into -domain
22+
"file(<tess_file_>),cell(<cell_id>)".
623

724
New in 4.9.0 (15 May 2024):
825
- module -T: added -per 1 for -morpho cube, added -ori ks (Kurdjumov-Sachs)

doc-dev/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Neper's Developer Documentation
1313
smoothing.rst
1414
1dlaguerre.rst
1515
ellipse.rst
16+
odfsampling.rst
1617
gpl.rst
1718
fdl.rst
1819

doc-dev/odfsampling.rst

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
.. _odfsampling:
2+
3+
Random sampling of ODFs
4+
=======================
5+
6+
Given an ODF defined on a mesh, either on elements (piecewise constant) or on nodes (piecewise linear), how can we sample it randomly?
7+
8+
Case of a uniform ODF
9+
---------------------
10+
11+
If the ODF is uniform (no texture), then we can choose the orientations without taking it into account, from random numbers (:math:`n_1`, :math:`n_2`, :math:`n_3`, :math:`n_4 \in [0,\,1]`):
12+
13+
- Euler-Bunge angles: :math:`\varphi_1=2\,\pi\,n_1`, :math:`\varphi_2= \hbox{acos} (2\,n_2-1)`, :math:`\varphi_3=2\,\pi\,n_3`
14+
- unit quaternion: if :math:`{{n_1}^2+{n_2}^2+{n_3}^2+{n_4}^2} \leq 1` then accept orientation :math:`q_i=n_i`
15+
- homochoric vector: if :math:`\sqrt{{n_1}^2+{n_2}^2+{n_3}^2} \leq 1` then accept orientation :math:`x_i=n_i`
16+
17+
Case of a non-uniform ODF
18+
-------------------------
19+
20+
.. note::
21+
22+
Reminder on the expressions of the volume element, :math:`dg`:
23+
24+
1. Rodrigues space:
25+
26+
- :math:`dg = \left(\frac{\rho}{1+\rho^2}\right)^2 \, d\rho \sin{\chi} \, d\chi \, d\zeta` (polar coordinates)
27+
- :math:`dg = \left(\frac{1}{1+\rho^2}\right)^2 \, dr_1 \, dr_2 \, dr_3` (rectangular coordinates)
28+
29+
- By definition, :math:`\int_g dg = \pi^2` (with :math:`\rho\in\left[0,\,+\infty\right[`, :math:`\chi\in\left[0,\,\pi\right]` and :math:`\zeta\in\left[0,\,2\,\pi\right]` or :math:`\left\{r_1,\, r_2,\, r_3\right\} \in \mathbb{R}^3`). If integration is done on a fundamental region, then the integral is equal to :math:`\pi^2/n_c`, where :math:`n_c` is the multiplicity (24 for cubic, etc.).
30+
31+
2. Euler space (Bunge convention):
32+
33+
- :math:`dg = \sin{\phi} \, d\varphi_1 \, d\phi \, d\varphi_2`
34+
35+
- By definition, :math:`\int_{\varphi_1=0}^{2\,\pi} \int_{\phi=0}^{\pi/2} \int_{\varphi_2=0}^{\pi/2} dg = \pi^2`
36+
37+
- :math:`\sqrt{\hbox{det}(g)} = \frac{1}{8\,\pi^2} \sin{\phi}`, where :math:`g` is the metric tensor
38+
39+
3. Homochoric space:
40+
41+
The integral of the ODF, :math:`f(g)`, over full orientation space is therefore equal to :math:`\pi^2`. The integral over the cubic fundamental region is equal to :math:`\pi^2/24`.
42+
43+
If the ODF is non-uniform, the frequency of orientations must adhere to the intensity of the ODF (by definition). One may distinguish random sampling and uniform sampling, however. Uniform sampling (just as we implemented it for the case of a uniform ODF) attempts to fit the ODF at best given the number of orientations available. Random sampling (just as we apply it to the case of a uniform ODF) follows the ODF from a statistical point of view, but does not attempt to fit it at best; it retains a random character. This is the case developed here.
44+
45+
Let the ODF be defined as
46+
47+
.. math::
48+
49+
\begin{equation}
50+
f(\boldsymbol{x}) = \frac{1}{V} \, \frac{dV(\boldsymbol{x})}{d\boldsymbol{x}},
51+
\end{equation}
52+
53+
where :math:`\boldsymbol{x}` is the orientation.
54+
55+
Rejection sampling (inefficient)
56+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
57+
58+
Let :math:`f_\text{max}` be the maximum of :math:`f`. The procedure is then the following:
59+
60+
1. Pick a random orientation, :math:`\boldsymbol{x}`, following a uniform ODF;
61+
2. Generate a random number :math:`t\in[0,\,1]`;
62+
3. if :math:`t < f(\boldsymbol{x}) / f_\text{max}`, then accept orientation.
63+
64+
Terminate when all orientations have been generated.
65+
66+
The efficiency of the method scales with :math:`1/f_\text{max}`; that is, the stronger the texture is, the more orientations need to be generated and tested to attain the desired number of orientations. One may also note that the evaluation of :math:`f` at a particular orientation may be costly (for large meshes), which makes the process relatively inefficient.
67+
68+
Inverse transform sampling (100% efficient)
69+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
70+
71+
.. note:: This is the method implemented in Neper.
72+
73+
The ODF is defined over (multidimensional) orientation space; however, the discretization of orientation space (its mesh elements) provides a unidimensional ODF function that depends on the orientations (the numbers of the mesh elements), :math:`f_u (x)`, where :math:`x` is an integer than varies from 1 to :math:`N` (the total number of elemental orientations). (Note that the respective positions if the elements have no influence.) The "frequency of occurrence" of an orientation represented by element :math:`x`, which can be seen as a *probability*, :math:`p_x`, is given by:
74+
75+
.. math::
76+
77+
\begin{equation}
78+
p_x = \frac{n_c}{\pi^2} \, v_x \, f_u(x)
79+
\end{equation}
80+
81+
where :math:`v_x` is the volume of orientation space that orientation :math:`x` represents (taking into account the orientation multiplicity), and :math:`f_u(x)` its ODF value, and :math:`n_c` is the multiplicity of the space (24 for cubic).
82+
83+
:math:`v_x` is computed by integration of :math:`dg` over the associated element. In practice, it is taken as the volume of the element multiplied by :math:`(1 / (1 + \rho^2))^2`, in Rodrigues space (:math:`\rho = \sqrt{{r_1}^2 + {r_2}^2 + {r_3}^2}` assumed constant). So, :math:`p_x` sums to 1.
84+
85+
Formally, the inverse transform sampling is based on the fact that, for any random variable :math:`X \in \mathbb{R}`, the random variable :math:`F_X^{-1}(U)` has the same probability density function as :math:`X`, where :math:`F_X^{-1}` is the generalized inverse of the cumulative distribution function :math:`F_X` of :math:`X` and :math:`U` is uniform on :math:`[0,\,1]`.
86+
87+
In the present case, discrete (random) variables are discussed. The cumulative distribution function can be expressed as
88+
89+
.. math::
90+
91+
\begin{equation}
92+
P(x) = \sum_{j\leq x} p_j
93+
\end{equation}
94+
95+
which is a step function. As a step function does not have an inverse, the concept of generalized inverse is of particular importance.
96+
97+
The generalized inverse of :math:`P` is:
98+
99+
.. math::
100+
101+
\begin{equation}
102+
P^-(y) = \hbox{inf}\left\{x \in \mathbb{R} : P(x) \geq y\right\}, y \in \mathbb{R}
103+
\end{equation}
104+
105+
Note that entire ranges of values of :math:`y` now correspond to a single value of :math:`x`.
106+
107+
The procedure then is to draw a random number between 0 and 1, :math:`y`, and compute the value of :math:`P^-(y)`. This value is the element from which we generate an orientation.
108+
109+
To complete the process, for any selected element, :math:`y`, the orientation is chosen randomly within the element. To do so, we pick a random position inside the element, following a uniform space distribution, using Rocchini and Cignoni's method (https://doi.org/10.1080/10867651.2000.10487528), which provides the orientation.
110+
111+
This method is direct and does not involve any testing or rejection. It is *almost* correct in the sense that steps 1 and 2 are correct, but step 3 assumes a uniform density of the space inside an element. This is reasonable assumption for properly conditioned spaces (such as Rodrigues space) and properly refined meshes, and is the same assumption as the one made to discretize the ODF itself.
112+
113+
Useful references:
114+
- https://link.springer.com/article/10.1007/s00186-013-0436-7
115+
- Morawiec's book for the rejection method
116+
- L13-Grain_Bndries_RFspace-15Mar16.pdf for the volume element
117+
- find a book in statistics for rejection and inverse sampling methods, which are standard

doc/conf.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
import sphinx_rtd_theme
1212

1313
project = u'Neper'
14-
version = u'4.9.1-6'
15-
release = u'4.9.1-6'
14+
version = u'4.10.0'
15+
release = u'4.10.0'
1616
author = u'Romain Quey'
1717
copyright = u'Romain Quey'
1818
language = 'en'

doc/exprskeys.rst

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -640,10 +640,36 @@ Key Descriptor Number of pa
640640
:data:`quaternion` quaternion 4
641641
========================== ======================================== =============================
642642

643-
The convention can be added to the descriptor, either :data:`active` or :data:`passive`, as in :data:`rodrigues:active`. When no convention is provided, :data:`active` is assumed.
643+
The convention can be added to the descriptor, either :data:`active` or :data:`passive`, as in :data:`rodrigues:active`. When no convention is provided, :data:`passive` is assumed.
644644

645645
Some options can take parameter values as argument, in which case the orientation must be expressed as :data:`<descriptor>(<parameter1>,<parameters2>,...)`. An example is :data:`rodrigues(0.1,0.2,0.3)`.
646646

647+
.. _orientation_convention:
648+
649+
Orientation Convention
650+
~~~~~~~~~~~~~~~~~~~~~~
651+
652+
The crystal coordinate systems are attached to the crystal lattice as illustrated below, in the case of cubic and hexagonal symmetries:
653+
654+
.. image:: imgs/directionconvention.png
655+
656+
The so-called "passive" orientation convention is used by default, which is based on the rotation of the sample coordinate system into the crystal coordinate system. Under this convention, the values of all :ref:`rotation_and_orientation_descriptors` are provided below for a simple (but representative) configuration that corresponds to a rotation of 30° about :math:`X_s`:
657+
658+
.. image:: imgs/orientationconvention.png
659+
660+
======================================== =============================
661+
**Descriptor** **Value** (angles in degrees)
662+
Rodrigues vector :math:`(0.267949192,\,0,\,0)`
663+
Euler angles (Bunge convention) :math:`(0,\,30,\,0)`
664+
Euler angles (Kocks convention) :math:`(270,\,30,\,90)`
665+
Euler angles (Roe convention) :math:`(270,\,30,\,90)`
666+
rotation matrix :math:`\left(\begin{array}{ccc}1 & 0 & 0 \\ 0 & 0.866025404 & 0.5 \\ 0 & -0.5 & 0.866025404\\\end{array}\right)`
667+
rotation axis / angle pair :math:`(1,\,0,\,0) / 30`
668+
quaternion :math:`(0.965925826,\,0.258819045,\,0,\,0)`
669+
======================================== =============================
670+
671+
The values of the orientation descriptors under the "active" convention are obtained by taking the opposite rotation.
672+
647673
.. _ideal_orientations:
648674

649675
Ideal Orientations
@@ -667,7 +693,7 @@ Keys are available for ideal orientations (lowercased is accepted):
667693
:data:`Copper2` :math:`(\overline{1}\,1\,2)[1\,\overline{1}\,1]`
668694
======================== ====================================
669695

670-
When loading orientations from an external file, use :data:`file(<file_name>[,des=<descriptor>])` where the orientation descriptor is among those listed above and is :data:`rodrigues:active` by default.
696+
When loading orientations from an external file, use :data:`file(<file_name>[,des=<descriptor>])` where the orientation descriptor is among those listed above and is :data:`rodrigues:passive` by default.
671697

672698
.. _orientation_fibers:
673699

doc/fileformat.rst

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,10 @@ and
7878
*edge
7979
<total_number_of_dom_edges>
8080
<dom_edge_id> <number_of_dom_vertices> [<dom_ver_1> <dom_ver_2>]
81+
<dom_edge_type>
82+
<number_of_params> <dom_edge_param1> <dom_edge_param2> ...
8183
<dom_edge_label>
82-
<number_of_dom_tess_edges> <edge_1> <edge_2> ...
84+
<number_of_dom_tess_edges> <dom_tess_edge_1> <dom_tess_edge_2> ...
8385
...
8486
*face
8587
<total_number_of_dom_faces>
@@ -88,8 +90,7 @@ and
8890
<dom_face_type>
8991
<number_of_params> <dom_face_param1> <dom_face_param2> ...
9092
<dom_face_label>
91-
<number_of_dom_tess_faces>
92-
<dom_tess_face_1> <dom_tess_face_2> ...
93+
<number_of_dom_tess_faces> <dom_tess_face_1> <dom_tess_face_2> ...
9394
...
9495
**periodic
9596
*general
@@ -127,7 +128,7 @@ where (with identifiers being integer numbers),
127128

128129
- :data:`**format` denotes the beginning of the format field.
129130

130-
- :data:`<format>` is the file format, currently `2.0` (character string).
131+
- :data:`<format>` is the file format, currently `3.5` (character string).
131132

132133
- :data:`**general` denotes the beginning of the general information field.
133134

@@ -257,6 +258,12 @@ where (with identifiers being integer numbers),
257258

258259
- :data:`<dom_ver_#>` are identifiers of the domain vertices of a domain edge or face.
259260

261+
- :data:`<dom_edge_type>` is the type of an edge.
262+
263+
- :data:`<number_of_params>` is the number of parameters.
264+
265+
- :data:`<dom_edge_param#>` are the parameters of a domain edge.
266+
260267
- :data:`<dom_edge_label>` is the label of a domain edge, formatted as :data:`x0y0`, :data:`x0y1`, :data:`x1y0`, ... (for a cubic domain).
261268

262269
- :data:`<number_of_dom_tess_edges>` is the number of tessellation edges of a domain edge.
@@ -273,8 +280,6 @@ where (with identifiers being integer numbers),
273280

274281
- :data:`<dom_face_type>` is the type of a face, among `plane`, `cylinder` or `sphere`.
275282

276-
- :data:`<number_of_params>` is the number of parameters of a domain face.
277-
278283
- :data:`<dom_face_param#>` are the parameters of a domain face. For a planar face, they are the parameters of the equation of the face, listed in the order :data:`<face_eq_d>`, :data:`<face_eq_a>`, :data:`<face_eq_b>` and :data:`<face_eq_c>`. For a cylindrical face, they are the coordinates of the base point, the axis and the radius. For a spherical face, they are the coordinates of the center and the radius.
279284

280285
- :data:`<dom_face_label>` is the label of a domain face, formatted as :data:`x0`, :data:`x1`, :data:`y0`, :data:`y1`, :data:`z0` or :data:`z1` (for a cubic domain). For a cylindrical domain, it is formatted as :data:`z0`, :data:`z1`, :data:`f1`, :data:`f2`, ... Otherwise, it is one of :data:`f1`, :data:`f2`, ... Edge and vertex labels are derived accordingly.
@@ -401,7 +406,7 @@ where
401406

402407
- :data:`**format` denotes the beginning of the format field.
403408

404-
- :data:`<format>` is the file format, currently `2.0` (character string).
409+
- :data:`<format>` is the file format, currently `2.2` (character string).
405410

406411
- :data:`**general` denotes the beginning of the general information field.
407412

@@ -572,7 +577,7 @@ where
572577

573578
- :data:`$MeshVersion` denotes the beginning of a mesh version field.
574579

575-
- :data:`<mesh_version>` is the mesh file version (currently :data:`2.2.3`).
580+
- :data:`<mesh_version>` is the mesh file version (currently :data:`2.3`).
576581

577582
- :data:`$EndMeshVersion` denotes the end of a mesh version field.
578583

@@ -769,7 +774,7 @@ where
769774

770775
Results can have integer values, real values, vectorial values or tensorial values. In the result files, values for the different entities (nodes, elements, etc.) are written on successive lines, with components written on successive columns (space delimited). The components of a vector, :data:`v`, are written as :data:`v1` :data:`v2` :data:`v3`. The components of a symmetrical tensor, :data:`t`, are written using Voigt notation, as :data:`t11` :data:`t22` :data:`t33` :data:`t23` :data:`t31` :data:`t12`. The components of a skwe-symmetrical tensor, :data:`t`, are written using :data:`t12` :data:`t13` :data:`t23`. The components of a non-symmetrical tensor, :data:`t`, are written as :data:`t11` :data:`t12` :data:`t13` :data:`t21` :data:`t22` :data:`t23` :data:`t31` :data:`t32` :data:`t33`.
771776

772-
The directory also contains a hidden file, :file:`.sim`, containing information on the simulation and the content of the simulation directory. This file is only for internal use and is formatted as follows:
777+
The directory also contains a hidden file, :file:`.sim`, containing information on the simulation and the content of the simulation directory. This file is only for internal use and is formatted as follows (the sections depend on the actual content of the simulation directory and most of them are optional):
773778

774779
.. code-block:: plain
775780
@@ -785,6 +790,8 @@ The directory also contains a hidden file, :file:`.sim`, containing information
785790
<msh_file>
786791
*ori
787792
<ori_file>
793+
*opt
794+
<opt_file>
788795
*bcs
789796
<bcs_file>
790797
*phase

doc/imgs/cubicconvention.asy

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
settings.outformat="pdf";
2+
3+
unitsize(3cm);
4+
5+
draw(shift((0.15,0.15))*scale(1.8,1.4)*polygon(4),invisible);
6+
7+
draw(scale(0.8)*polygon(4));
8+
draw(circle((0,0),0.025), linewidth(0.8));
9+
10+
// First graph
11+
draw((0,0)--(1,0), Arrow);
12+
draw((0,0)--(0,1), Arrow);
13+
label("$X_c$", (1,0), N);
14+
label("$Y_c$", (0,1), E);
15+
label("$Z_c$", (0,0), SW);

doc/imgs/directionconvention.png

12 KB
Loading

doc/imgs/hexagonalconvention.asy

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
settings.outformat="pdf";
2+
3+
unitsize(3cm);
4+
5+
draw(shift((0.15,0.15))*scale(1.8,1.4)*polygon(4),invisible);
6+
7+
draw(scale(0.8)*polygon(6));
8+
draw(circle((0,0),0.025), linewidth(0.8));
9+
10+
// First graph
11+
draw((0,0)--(1,0), Arrow);
12+
draw((0,0)--(0,1), Arrow);
13+
label("$X_c$", (1,0), N);
14+
label("$Y_c$", (0,1), E);
15+
label("$Z_c$", (0,0), SW);

doc/imgs/orientationconvention.png

9.72 KB
Loading

0 commit comments

Comments
 (0)