Nutils 8 Idiyappam
Nutils 8.0 was released on July 28th, 2023.
What's New?
These are the main additions and changes since Nutils 7 Hiyamugi.
New: SI module for physical units
The SI module provides a framework for checking the dimensional consistency of a formulation at runtime, as well as tools to convert between different units for post processing. Extensive documentation can be found in the SI module. The framework can be seen in action in the cahnhilliard example, with more examples to be converted in future.
New: support for einsum and other Numpy operations
Support for Numpy operations on Nutils arrays has been extended to include:
numpy.choose
numpy.cross
numpy.diagonal
numpy.einsum
numpy.interp
(array support limited tox
argument)numpy.linalg.det
numpy.linalg.eig
numpy.linalg.eigh
numpy.linalg.inv
numpy.linalg.norm
numpy.searchsorted
(array support limited tov
argument)
New: test fields and residual functionals
The nutils.solver
methods have been generalized to accept scalar valued
functionals, from which residual vectors are derived through differentiation.
To this end, a trial/test function pair can be specified as a solve target
separated by a colon, as in the following example:
ns.add_field(('u', 'v'), topo.basis('std', degree=1))
res = topo.integral('∇_i(u) ∇_i(v) dV' @ ns, degree=2)
args = solver.newton('u:v', res).solve(1e-10)
Multiple fields can either comma-joined or provided as a tuple. Note that the colon automatically triggers a new-style dictionary return value, even in absence of a trialing comma as in the above example.
New: Namespace.add_field
The namespace from the nutils.expression_v2
module newly provides the
nutils.expression_v2.Namespace.add_field
method, as a convenient shorthand
for creating fields with the same name as their arguments. That is:
ns.add_field(('u', 'v'), topo.basis('std', degree=1), shape=(2,))
is equivalent to
basis = topo.basis('std', degree=1)
ns.u = function.dotarg('u', basis, shape=(2,))
ns.v = function.dotarg('v', basis, shape=(2,))
New: shorthand notation for multiple solver targets
Multiple solver targets can now be specified as a comma-separated string, as a shorthand for the string tuple that will remain a valid argument. This means the following two invocations are equivalent:
args = solver.newton(('u', 'p'), (ures, pres)).solve(1e-10)
args = solver.newton('u,p', (ures, pres)).solve(1e-10)
To distinguish single-length tuples from the single argument legacy notation, the former requires a trailing comma. I.e., the following are NOT equivalent:
args = solver.newton('u,', (ures,)).solve(1e-10)
u = solver.newton('u', ures).solve(1e-10)
New: nearest-neighbour interpolation in sample.asfunction, sample.basis
The sample methods asfunction
and basis
have a new interpolation argument
that take the string values "none" (default) or "nearest". The latter activates
a new mode that allows evaluation of sampled data on other samples than the
original by selecting the point that is closest to the target.
New: function.linearize
Similar to derivative
, the new function linearize
takes the derivative of
an array to one or more arguments, but with the derivative directions
represented by arguments rather than array axes. This is particularly useful in
situations where weak forms are made up of symmetric, energy like components,
combined with terms that require dedicated test fields.
New: option to disable Newton's line search
The linesearch
argument of solver.newton
can now receive the None
value
to indicate that line search is to be disabled. Additionally, the legacy
arguments searchrange
and rebound
have been deprecated, and should be
replaced by linesearch=solver.NormBased(minscale=searchrange[0], acceptscale=searchrange[1], maxscale=rebound)
.
New: iteration count via info.niter
The info struct returned by solve_withinfo
newly contains the amount of
iterations as the niter
attribute:
res, info = solver.newton('u:v', res).solve_withinfo(1e-10, maxiter=10)
assert info.niter <= 10
Improved: more efficient trimming
The trim routine (which is used for the Finite Cell Method) is rewritten for speed and to produce more efficient quadrature schemes. The changes relate to the subdivision at the deepest refinement level. While this step used to introduce auxiliary vertices at every dimension (lines, faces, volumes), the new implementation limits the introduction of vertices to the line segments only, resulting in a subdivision that consists of fewer simplices and consequently fewer quadrature points.
Changed: solve, solve_withinfo arguments
Solver methods newton, minimize and pseudotime have their function signature slightly changed:
- The tol argument (used to define the stop criterion) has been made mandatory. As the default value used to be 0 - an unreacheable value in practice - the argument was effectively mandatory already, which this change formalizes.
- The maxiter argument was off by 1, leading maxiter=n to accept n+1 iterations. This mistake is now fixed, which may break applications that relied on the former erroneous behaviour.
Fixed: locate points on trimmed topologies with the skip_missing flag set
The locate
method has a skip_missing
argument that instructs the method to
silently drop points that can not be located on the topology. This setting was
partially ignored by trimmed topologies which could lead to a LocateError
despite the flag being set. This issue is now fixed.
Removed: Nutils configuration file
Support for the Nutils configuration file (which used to be located in either ~/.nutilsrc or ~/.config/nutils/config) has been removed. Instead, the following environment variables can be set to override the default Nutils settings:
- NUTILS_PDB = yes|no
- NUTILS_GRACEFULEXIT = yes|no
- NUTILS_OUTROOTDIR = path/to/html/logs
- NUTILS_OUTROOTURI = uri/to/html/logs
- NUTILS_SCRIPTNAME = myapp
- NUTILS_OUTDIR = path/to/this/html/log
- NUTILS_OUTURI = uti/to/this/html/log
- NUTILS_RICHOUTPUT = yes|no
- NUTILS_VERBOSE = 1|2|3|4
- NUTILS_MATRIX = numpy|scipy|mkl|auto
- NUTILS_NPROCS = 1|2|...
- NUTILS_CACHE = yes|no
- NUTILS_CACHEDIR = path/to/cache
Deprecated: function methods that have Numpy equivalents
The nutils.function
methods that have direct equivalents in the numpy
module (function.sum
, function.sqrt
, function.sin
, etc) have been
deprecated in favour of using Numpy's methods (numpy.sum
, numpy.sqrt
,
numpy.sin
, etc) and will be removed in the next release. Ultimately, only
methods that relate to the variable nature of function arrays and therefore
have no Numpy equivalent, such as function.grad
and function.normal
, will
remain in the function module.
Be aware that some functions were not 100% equivalent to their Numpy
counterpart. For instance, function.max
is the equivalent to numpy.maximum
,
as the deprecation message helpfully points out. More problematically,
function.dot
behaves very differently from both numpy.dot
and
numpy.matmul
. Porting the code over to equivalent instructions will therefore
require some attention.
Deprecated: Array.dot for ndim != 1
The nutils.function.Array.dot
method is incompatible with Numpy's equivalent
method for arrays of ndim != 1, or when axes are specified (which Numpy does
not allow). Aiming for 100% compatibility, the next release cycle will remove
the axis argument and temporarily forbid arguments of ndim != 1. The release
cycle thereafter will re-enable arguments with ndim != 1, with logic equal to
Numpy's method. In the meantime, the advice is to rely on numpy.dot
,
numpy.matmul
or the @
operator instead.
Deprecated: Array.sum for ndim > 1 without axis argument
The nutils.function.Array.sum
method by default operates on the last axis.
This is different from Numpy's behavour, which by default sums all axes. Aiming
for 100% compatibility, the next release cycle will make the axis argument
mandatory for any array of ndim > 1. The release cycle thereafter will
reintroduce the default value to match Numpy's. To prepare for this, relying on
the current default now triggers a deprecation warning.