Skip to content

Commit

Permalink
Unlock -n ... -morpho lamellar
Browse files Browse the repository at this point in the history
It is now possible to specify the number of lamellae of a lamellar
morphology using simply -n.

Also added tessellation key length(...).
  • Loading branch information
rquey committed Aug 27, 2024
1 parent 5b071e6 commit a7ce0c6
Show file tree
Hide file tree
Showing 22 changed files with 1,707 additions and 77 deletions.
4 changes: 3 additions & 1 deletion VERSIONS
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
New in 4.9.1-3 (23 Aug 2024):
New in 4.9.1-4 (27 Aug 2024):
- module -T: added -n ... -morpho lamellae and (the equivalent)
-morpho lamellar(n=...)", added tessellation key length(d_x,dd_y,d_z).
- made minor fixes and improvements.

New in 4.9.0 (15 May 2024):
Expand Down
4 changes: 2 additions & 2 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
import sphinx_rtd_theme

project = u'Neper'
version = u'4.9.1-3'
release = u'4.9.1-3'
version = u'4.9.1-4'
release = u'4.9.1-4'
author = u'Romain Quey'
copyright = u'Romain Quey'
language = 'en'
Expand Down
1 change: 1 addition & 0 deletions doc/exprskeys.rst
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ To turn a key value into a value relative to the mean over all entities (e.g. th
:data:`domver` domain vertex (-1 if undefined) ver
:data:`scale` scale ver, edge, face, poly, cell [#multiscale_entity]_
:data:`length` length edge
:data:`length(<d_x>,<d_y>,<d_z>)` directional length along :math:`(d_x,d_y,d_z)` (in 2D, :data:`d_z` can be omitted) edge, face, poly
:data:`area` surface area face, poly, group
:data:`vol` volume poly, group
:data:`size` size (surface area/volume in 2D/3D) cell, group
Expand Down
26 changes: 14 additions & 12 deletions doc/neper_t.rst
Original file line number Diff line number Diff line change
Expand Up @@ -202,23 +202,25 @@ These options can be used to set the cell morphology.

- :data:`tocta(<N>)`: regular tessellation into truncated octahedra, where :data:`<N>` is the number of cells along a direction;

- :data:`lamellar(w=<width>[,v=<normal>][,pos=<pos>][,reps=<reps>])`: lamellar morphology, where :data:`<width>` is the absolute lamella width or a series of absolute lamella widths combined with :data:`:`, and :data:`<normal>` is the lamella plane normal and can be:
- :data:`lamellar([w=<width>][,n=<n>][,v=<normal>][,pos=<pos>][,reps=<reps>])`: lamellar morphology, where :data:`<width>` is the absolute lamella width or a series of absolute lamella widths combined with :data:`:`, :data:`<n>` is the number of lamellae, :data:`<normal>` is the lamella plane normal, :data:`<pos>` is the position of the first lamella, and :data:`<reps>` is a relative tolerance on the width of the last lamella. :data:`width=\<width\>` and :data:`n=\<n\>` are mutually exclusive. The number of lamellae can also be specified using option :option:`-n`. Specifying a number of cells (using option :option:`-n` or :data:`n=\<n\>`) enforces :data:`pos=start` (or equivalently :data:`pos=optimal`, as described below).

- :data:`random`: randomly-distributed normals taken from a uniform distribution (the default);
- :data:`(<dir_x>,<dir_y>,<dir_z>)`: a specific direction of space, (:data:`dir_x`, :data:`dir_y`, :data:`dir_z`);
- :data:`crysdir(<crysdir_x>,<crysdir_y>,<crysdir_z>)`: a specific direction of the parent crystal, (:data:`<crysdir_x>`, :data:`<crysdir_y>`, :data:`<crysdir_z>`).
- :data:`<normal>` (the lamella plane normal) can be:

:data:`pos` is the position of the first lamella and can be:
- :data:`random`: randomly-distributed normals taken from a uniform distribution (the default);
- :data:`(<dir_x>,<dir_y>,<dir_z>)`: a specific direction of space, (:data:`dir_x`, :data:`dir_y`, :data:`dir_z`);
- :data:`crysdir(<crysdir_x>,<crysdir_y>,<crysdir_z>)`: a specific direction of the parent crystal, (:data:`<crysdir_x>`, :data:`<crysdir_y>`, :data:`<crysdir_z>`).

- :data:`random`: random position (the default);
- :data:`optimal`: optimal position, i.e. so that lamellae at the start *and* end of the domain are of lengths as close as possible to nominal (along direction :data:`<dir>`);
- :data:`start`: first lamella starting full-width from the start point of the domain (along direction :data:`<dir>`);
- :data:`half`: first lamella starting half-width from the start point of the domain (along direction :data:`<dir>`).
- :data:`<factor>`: lamella starting with a width equal to :data:`<factor>` times the nominal width (between :data:`0` and :data:`1`), from the start point of the domain (along direction :data:`<dir>`).
- :data:`<pos>` (the position of the first lamella) can be:

:data:`reps` is a relative tolerance on the width of the last lamella (default :data:`1e-2`) - a lamella is allowed to be larger than nominal, within the specified relative tolerance, to avoid the occurence of unrealistically thin lamella.
- :data:`random`: random position (the default);
- :data:`optimal`: optimal position, i.e. so that lamellae at the start *and* end of the domain are of lengths as close as possible to nominal (along direction :data:`<dir>`);
- :data:`start`: first lamella starting full-width from the start point of the domain (along direction :data:`<dir>`);
- :data:`half`: first lamella starting half-width from the start point of the domain (along direction :data:`<dir>`).
- :data:`<factor>`: lamella starting with a width equal to :data:`<factor>` times the nominal width (between :data:`0` and :data:`1`), from the start point of the domain (along direction :data:`<dir>`).

In the case of a multiscale tessellation, a :ref:`multiscale cell file <multiscale_cell_file>` can be provided as value of :data:`w`, :data:`v`, and :data:`pos`.
- :data:`<reps>` (default :data:`1e-2`) is so that a lamella is allowed to be larger than nominal, within the specified relative tolerance, to avoid the occurence of unrealistically thin lamella.

In the case of a multiscale tessellation, a :ref:`multiscale cell file <multiscale_cell_file>` can be provided as value of :data:`w`, :data:`n`, :data:`v`, and :data:`pos`.

**Custom morphological properties** can be defined using :data:`<property>:\<value\>`. The properties and the possible corresponding values can be:

Expand Down
2 changes: 1 addition & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ if(POLICY CMP0077)
cmake_policy(SET CMP0077 NEW)
endif()

set(NEPER_VERSION \"4.9.1-3\")
set(NEPER_VERSION \"4.9.1-4\")
project(neper)

if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8.1)
Expand Down
5 changes: 2 additions & 3 deletions src/neper_t/net_input/net_input2.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,8 @@ net_input_treatargs (int fargc, char **fargv, int argc, char **argv,
ut_print_message (2, 2, "Option `-morpho square' requires `-dim 2'.");
// testing consistency between morpho = lamellar and n, which must be from_morpho
for (i = 1; i <= (*pIn).levelqty; i++)
if ((!strncmp ((*pIn).morpho[i], "cube", 4)
|| !strncmp ((*pIn).morpho[i], "lamellar", 8))
&& strcmp ((*pIn).n[i], "from_morpho") != 0)
if ((!strncmp ((*pIn).morpho[i], "cube", 4))
&& strcmp ((*pIn).n[i], "from_morpho"))
ut_print_message (2, 2, "`-morpho %s' requires `-n from_morpho'.\n",
(*pIn).morpho[i]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,25 @@ net_tess_lam_seed (struct IN_T In, int level, char *morpho,
int dcell, struct TESS Dom, struct SEEDSET *SSet,
struct SEEDSET *pSSet)
{
int wqty, vqty;
int wqty;
int *n = NULL;
double reps, *w = NULL, *v = NULL;
char *pos = NULL;
char *wtype = NULL, *vtype = NULL, *postype = NULL;
char *ntype = NULL, *wtype = NULL, *vtype = NULL, *postype = NULL;

ut_string_string ("standard", &(*pSSet).Type);

net_tess_lam_seed_readargs (morpho, MTess, Tess, dtess, dcell, &wtype, &w,
&wqty, &vtype, &v, &vqty, &postype, &pos, &reps);
net_tess_lam_seed_readargs (In, level, morpho, MTess, Tess, dtess, dcell, &ntype, &n,
&wtype, &w, &wqty, &vtype, &v, &postype, &pos, &reps);

net_tess_lam_seed_set (In, level, MTess, Tess, dtess, dcell, Dom, wtype, w,
wqty, vtype, v, vqty, postype, pos, reps, SSet, pSSet);
net_tess_lam_seed_set (In, level, MTess, Tess, dtess, dcell, Dom, ntype, n, &wtype, &w,
&wqty, vtype, v, postype, pos, reps, SSet, pSSet);

ut_free_1d_int (&n);
ut_free_1d (&v);
ut_free_1d (&w);
ut_free_1d_char (&pos);
ut_free_1d_char (&ntype);
ut_free_1d_char (&vtype);
ut_free_1d_char (&wtype);
ut_free_1d_char (&postype);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,20 @@
#include"net_tess_lam_seed_.h"

int
net_tess_lam_seed_readargs (char *morpho, struct MTESS MTess,
net_tess_lam_seed_readargs (struct IN_T In, int level, char *morpho, struct MTESS MTess,
struct TESS *Tess, int domtess, int dompoly,
char **pntype, int **pn,
char **pwtype, double **pw, int *pwqty,
char **pvtype, double **pv, int *pvqty,
char **pvtype, double **pv,
char **ppostype, char **ppos, double *preps)
{
int i, varqty;
int i, j, varqty, tmpi;
double *tmp = NULL;
char **vars = NULL, **vals = NULL;
double *n_double = NULL;

(*pwqty) = 0;
(*pvqty) = 0;
ut_string_string ("none", pntype);
ut_string_string ("none", pwtype);
ut_string_string ("random", pvtype);
ut_string_string ("scal", ppostype);
Expand All @@ -25,15 +27,33 @@ net_tess_lam_seed_readargs (char *morpho, struct MTESS MTess,

ut_string_function (morpho, NULL, &vars, &vals, &varqty);

if (strcmp (In.n[level], "from_morpho"))
{
varqty++;
vars = ut_realloc_1d_pchar_null (vars, varqty, 1);
vals = ut_realloc_1d_pchar_null (vals, varqty, 1);
ut_string_string ("n", vars + varqty - 1);
ut_string_string (In.n[level], vals + varqty - 1);
}

for (i = 0; i < varqty; i++)
{
if (!strcmp (vars[i], "w"))
if (!strcmp (vars[i], "n"))
{
net_tess_lam_seed_readargs_w (vals[i], MTess, Tess, domtess, dompoly,
pntype, &n_double, &tmpi);
(*pn) = ut_alloc_1d_int (1);
for (j = 0; j < 1; j++)
(*pn)[j] = n_double[j];
}

else if (!strcmp (vars[i], "w"))
net_tess_lam_seed_readargs_w (vals[i], MTess, Tess, domtess, dompoly,
pwtype, pw, pwqty);

else if (!strcmp (vars[i], "v"))
net_tess_lam_seed_readargs_v (vals[i], MTess, Tess, domtess, dompoly,
pvtype, pv, pvqty);
pvtype, pv);

else if (!strcmp (vars[i], "pos"))
net_tess_lam_seed_readargs_pos (vals[i], MTess, Tess, domtess, dompoly,
Expand All @@ -50,25 +70,30 @@ net_tess_lam_seed_readargs (char *morpho, struct MTESS MTess,
abort ();
}

if (*pwqty <= 0)
ut_print_message (2, 2, "missing lamellar width!\n");
if ((strcmp (*pntype, "none") || strcmp (In.n[level], "from_morpho")) && strcmp (*pwtype, "none"))
ut_print_message (2, 2, "w and n are mutually exclusive.");

if (!strcmp (*pntype, "none") && !strcmp (*pwtype, "none") && !strcmp (In.n[level], "from_morpho"))
ut_print_message (2, 2, "Either w or n must be defined.");

ut_free_2d_char (&vars, varqty);
ut_free_2d_char (&vals, varqty);
ut_free_1d (&tmp);
ut_free_1d (&n_double);

return 0;
}

int
net_tess_lam_seed_set (struct IN_T In, int level, struct MTESS MTess,
struct TESS *Tess, int dtess, int dcell,
struct TESS Dom, char *wtype, double *w, int wqty,
char *vtype, double *v, int vqty, char *postype,
struct TESS Dom, char *ntype, int *n,
char **pwtype, double **pw, int *pwqty,
char *vtype, double *v, char *postype,
char *pos, double reps, struct SEEDSET *SSet,
struct SEEDSET *pSSet)
{
double *n = ut_alloc_1d (3);
double *normal = ut_alloc_1d (3);
gsl_rng *r = gsl_rng_alloc (gsl_rng_ranlxd2);

(void) level;
Expand All @@ -91,14 +116,14 @@ net_tess_lam_seed_set (struct IN_T In, int level, struct MTESS MTess,
net_ori_mtess_randseed (MTess, Tess, dtess, dcell, SSet, 1, pSSet);

gsl_rng_set (r, (*pSSet).Random);
net_tess_lam_seed_set_normal (SSet, dtess, dcell, r, vtype, v, vqty, n);
net_tess_lam_seed_set_normal (SSet, dtess, dcell, r, vtype, v, normal);

net_tess_lam_seed_set_lam (Dom, r, n, wtype, w, wqty, postype, pos, reps, pSSet);
net_tess_lam_seed_set_lam (Dom, r, normal, ntype, n, pwtype, pw, pwqty, postype, pos, reps, pSSet);

net_tess_lam_seed_set_finalize (pSSet);

gsl_rng_free (r);
ut_free_1d (&n);
ut_free_1d (&normal);

return 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,10 @@ net_tess_lam_seed_readargs_w (char *value, struct MTESS MTess,
int
net_tess_lam_seed_readargs_v (char *value, struct MTESS MTess,
struct TESS *Tess, int domtess, int dompoly,
char **pvtype, double **pv, int *pvqty)
char **pvtype, double **pv)
{
char *mid = NULL;

(*pvqty) = 0;

if (!strcmp (value, "random"))
ut_string_string ("random", pvtype);
else if (!strncmp (value, "random(", 7))
Expand All @@ -68,7 +66,6 @@ net_tess_lam_seed_readargs_v (char *value, struct MTESS MTess,
else if (ut_string_isfilename (value))
{
ut_string_string ("file", pvtype);
(*pvqty) = 1;
(*pv) = ut_alloc_1d (3);
neut_mtess_tess_poly_mid (MTess, Tess[domtess], dompoly, &mid);
net_multiscale_arg_1d_fscanf (value, mid, *pv, 3);
Expand Down Expand Up @@ -121,7 +118,7 @@ net_tess_lam_seed_set_init (struct SEEDSET *pSSet)

int
net_tess_lam_seed_set_normal (struct SEEDSET *SSet, int dtess, int dcell,
gsl_rng * r, char *vtype, double *v, int vqty,
gsl_rng * r, char *vtype, double *v,
double *n)
{
int dim = SSet[1].Dim;
Expand All @@ -131,7 +128,7 @@ net_tess_lam_seed_set_normal (struct SEEDSET *SSet, int dtess, int dcell,
if (dtess != 0)
q = SSet[dtess].SeedOri[dcell];

if (!strcmp (vtype, "file") && vqty == 1)
if (!strcmp (vtype, "file"))
ut_array_1d_memcpy (v, 3, n);

else if (!strncmp (vtype, "random", 6))
Expand Down Expand Up @@ -200,30 +197,31 @@ net_tess_lam_seed_set_normal (struct SEEDSET *SSet, int dtess, int dcell,
}

int
net_tess_lam_seed_set_lam (struct TESS Dom, gsl_rng * r, double *n,
char *wtype, double *w, int wqty, char *postype,
char *pos, double reps, struct SEEDSET *pSSet)
net_tess_lam_seed_set_lam (struct TESS Dom, gsl_rng * r, double *normal,
char *ntype, int *n,
char **pwtype, double **pw, int *pwqty,
char *postype, char *pos, double reps, struct SEEDSET *pSSet)
{
int w_id;
double coo, distmin, distmax;
double *plane = ut_alloc_1d (4);

net_tess_lam_seed_set_w_pre (r, Dom, n, wtype, w, wqty, postype, pos, plane,
net_tess_lam_seed_set_w_pre (r, Dom, normal, ntype, n, pwtype, pw, pwqty, postype, pos, plane,
reps, &distmin, &distmax);

(*pSSet).N = 0;
coo = plane[0];
w_id = -1;
do
{
w_id = ut_array_rotpos (0, wqty - 1, w_id, 1);
coo += w[w_id];
w_id = ut_array_rotpos (0, *pwqty - 1, w_id, 1);
coo += (*pw)[w_id];
if (coo < distmin)
continue;

net_tess_lam_seed_set_addlam (coo, n, w[w_id], wqty > 1 ? w_id : -1, pSSet);
net_tess_lam_seed_set_addlam (coo, normal, (*pw)[w_id], *pwqty > 1 ? w_id : -1, pSSet);
}
while (coo < distmax - reps * w[w_id]);
while (coo < distmax - reps * (*pw)[w_id]);

ut_free_1d (&plane);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,31 @@
#include"net_tess_lam_seed_.h"

int
net_tess_lam_seed_set_w_pre (gsl_rng * r, struct TESS Dom, double *n,
char *wtype, double *w, int wqty, char *postype,
char *pos, double *plane, double reps,
net_tess_lam_seed_set_w_pre (gsl_rng * r, struct TESS Dom, double *normal,
char *ntype, int *n, char **pwtype, double **pw, int *pwqty,
char *postype, char *pos, double *plane, double reps,
double *pdistmin, double *pdistmax)
{
int i;
double fact, *dist = ut_alloc_1d (Dom.VerQty + 1);
double tmp1, tmp2, wall = ut_array_1d_sum (w, wqty);
double tmp1, tmp2, dirlength, wall;

(void) wtype;
(void) postype;
if (strcmp (*pwtype, "none"))
wall = ut_array_1d_sum (*pw, *pwqty);
else if (strcmp (ntype, "none"))
{
neut_tess_poly_dir_length (Dom, 1, normal, &dirlength);
*pwqty = 1;
(*pw) = ut_alloc_1d (1);
(*pw)[0] = dirlength / n[0];
wall = (*pw)[0];
ut_string_string ("from_n", pwtype);
ut_string_string ("start", &pos);
}
else
abort ();

ut_array_1d_memcpy (n, 3, plane + 1);
ut_array_1d_memcpy (normal, 3, plane + 1);

// distmin and distmax are the min and max values from the plane (with
// constant = 0) and the vertices
Expand All @@ -34,7 +46,7 @@ net_tess_lam_seed_set_w_pre (gsl_rng * r, struct TESS Dom, double *n,
else if (!strcmp (pos, "start"))
plane[0] = *pdistmin;
else if (!strcmp (pos, "half"))
plane[0] = *pdistmin - 0.5 * w[0];
plane[0] = *pdistmin - 0.5 * (*pw)[0];
else if (!strcmp (pos, "optimal"))
{
tmp1 = (*pdistmax - *pdistmin) / wall;
Expand All @@ -47,7 +59,7 @@ net_tess_lam_seed_set_w_pre (gsl_rng * r, struct TESS Dom, double *n,
plane[0] = *pdistmin - (tmp2 - tmp1) * wall / 2;
}
else if (sscanf (pos, "%lf", &fact))
plane[0] = *pdistmin - fact * w[0];
plane[0] = *pdistmin - fact * (*pw)[0];
else
ut_print_message (2, 3, "Failed to process expression `pos=%s'.\n",
postype);
Expand All @@ -58,14 +70,14 @@ net_tess_lam_seed_set_w_pre (gsl_rng * r, struct TESS Dom, double *n,
}

int
net_tess_lam_seed_set_addlam (double distcur, double *n, double w, int w_id,
net_tess_lam_seed_set_addlam (double distcur, double *normal, double w, int w_id,
struct SEEDSET *pSSet)
{
(*pSSet).N++;
(*pSSet).LamEq = ut_realloc_2d_addline ((*pSSet).LamEq, (*pSSet).N + 1, 4);
(*pSSet).LamWidth = ut_realloc_1d ((*pSSet).LamWidth, (*pSSet).N + 1);

ut_array_1d_memcpy (n, 3, (*pSSet).LamEq[(*pSSet).N] + 1);
ut_array_1d_memcpy (normal, 3, (*pSSet).LamEq[(*pSSet).N] + 1);
(*pSSet).LamEq[(*pSSet).N][0] = distcur;
(*pSSet).LamWidth[(*pSSet).N] = w;

Expand Down
Loading

0 comments on commit a7ce0c6

Please sign in to comment.