Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

partition #488

Draft
wants to merge 119 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
119 commits
Select commit Hold shift + click to select a range
fe1a100
fix missing kwargs in Immutable.{edit,__reduce__}
joostvanzwieten Apr 28, 2020
6e0a644
fix parsing power expr. with const scalar base
joostvanzwieten Apr 28, 2020
f1a5923
support scientific notation in expressions
joostvanzwieten Apr 28, 2020
ef29e4a
doc fixes
joostvanzwieten Apr 28, 2020
a616446
remove Topology.elem_project
joostvanzwieten Mar 12, 2020
edce9dc
disable multipatch unittests
joostvanzwieten Feb 3, 2020
81449b5
disable unittests involving bifurcate
joostvanzwieten Jun 13, 2019
75b8c74
remove {transform,function}.Bifurcate and friends
joostvanzwieten Feb 13, 2020
d3ee438
remove first of two function.{normal,grad}
joostvanzwieten Jan 8, 2020
7680c39
restructure function.Basis tests
joostvanzwieten Jan 7, 2020
c001db8
use strict type checking in Transforms sequences
joostvanzwieten Feb 13, 2020
6da6396
don't pop the head of transform chains
joostvanzwieten Feb 13, 2020
5995879
remove root trans item from StructuredTransforms
joostvanzwieten Feb 13, 2020
616b089
don't use Transforms.fromdims
joostvanzwieten Feb 11, 2020
310110b
update documentation TransformItem
joostvanzwieten Mar 16, 2020
e335abc
remove Opposite.simplified
joostvanzwieten Mar 17, 2020
4a81ed8
add function.Root
joostvanzwieten Feb 3, 2020
4d6a85b
add function.Subsample
joostvanzwieten Mar 16, 2020
353476d
add function.SubsampleMeta
joostvanzwieten Mar 16, 2020
40e6bb7
attach Root to Topology, Sample, Function
joostvanzwieten Feb 7, 2020
46f9adf
replace _transforms, _points with subsamples
joostvanzwieten Mar 16, 2020
d0963ad
replace ndims with subsamples in prepare_eval
joostvanzwieten Mar 16, 2020
fd53983
extend TransformsIndexWithTail with head
joostvanzwieten Jun 20, 2019
e509276
generalize derivatives of function.Argument
joostvanzwieten Jun 20, 2019
c08174c
add transform.linear, function.Linear
joostvanzwieten Jun 24, 2019
5f0e6d9
add numeric.gramschmidt, function.GramSchmidt
joostvanzwieten Jan 8, 2020
82a3d5c
add derivatives to rootcoords
joostvanzwieten Jun 20, 2019
b5512b0
compute grad(geom) using rootgradient
joostvanzwieten Jun 20, 2019
d9761b3
compute jacobian using rootgradient
joostvanzwieten Jun 24, 2019
412aae8
compute topo.locate with rootgradient
joostvanzwieten Jun 24, 2019
df91c23
drop localgradient, LocalCoords
joostvanzwieten Jun 24, 2019
78f0240
replace Transforms.fromdims with todims
joostvanzwieten Feb 13, 2020
fecab4f
impl det for transform.Updim,ScaledUpdim
joostvanzwieten Jan 12, 2020
f0451ab
add basis for manifold, normal space to Points
joostvanzwieten Jan 8, 2020
24421af
add ndimsnormal param, attr to Element
joostvanzwieten Jan 28, 2020
38eef35
WIP: wrap MosaicRef in WithManifoldEdgesRef
joostvanzwieten Jan 10, 2020
eb9c0e0
add TrimmedEdgesTransforms
joostvanzwieten Jan 28, 2020
ebe9b52
WIP
joostvanzwieten Feb 18, 2020
f7d0117
replace points evalarg with *subsamples
joostvanzwieten Mar 1, 2020
57de536
add function.ProductBasis
joostvanzwieten Mar 15, 2020
8994a38
reimplement ProductTopology
joostvanzwieten Mar 15, 2020
a233378
make mesh.rectilinear,.unitsquare tensorial
joostvanzwieten Mar 15, 2020
3065e8d
reenable mesh.newrectilinear tests
joostvanzwieten Mar 15, 2020
86d82d9
WIP: ProductSample, ProductBasis
joostvanzwieten Mar 2, 2020
29ee6e1
fixes
joostvanzwieten Mar 2, 2020
cf9d19d
WIP
joostvanzwieten Mar 3, 2020
db19da2
WIP
joostvanzwieten Mar 3, 2020
bf55a5e
WIP
joostvanzwieten Mar 3, 2020
596697c
update
joostvanzwieten Mar 4, 2020
6f882ba
update
joostvanzwieten Mar 6, 2020
adcf692
update
joostvanzwieten Mar 6, 2020
67675d2
f compute jacobian using rootgradient after introducing subsamplemeta
joostvanzwieten Mar 9, 2020
a5f8031
update
joostvanzwieten Mar 9, 2020
9b04cb7
updates
joostvanzwieten Mar 10, 2020
d1bc94e
add special case Sample implementations
joostvanzwieten Mar 10, 2020
1683869
add topology.StructuredLine
joostvanzwieten Mar 10, 2020
775a935
add Transforms.linear
joostvanzwieten Mar 10, 2020
f2df8e8
updates
joostvanzwieten Mar 21, 2020
b2c312a
improve Constant.simplified invariant axes check
joostvanzwieten Mar 21, 2020
05acfa9
implement intdata dot weights using function.*
joostvanzwieten Mar 22, 2020
260c059
update
joostvanzwieten Mar 22, 2020
be5a7fe
update
joostvanzwieten Mar 23, 2020
a769469
rename Transforms.linear to Transforms.basis
joostvanzwieten Mar 23, 2020
2ed1632
update
joostvanzwieten Mar 23, 2020
14a9263
fixes
joostvanzwieten Mar 23, 2020
678214b
implement revolved
joostvanzwieten Mar 23, 2020
7df268b
update
joostvanzwieten Mar 24, 2020
c0b4912
fixes
joostvanzwieten Mar 25, 2020
4c0f0a2
update
joostvanzwieten Mar 25, 2020
906104d
fix subsamplemeta with points is None
joostvanzwieten Apr 14, 2020
3b48830
fix trimming
joostvanzwieten May 11, 2020
f404370
preserve topological structure of empty topos
joostvanzwieten Jun 15, 2020
0ba778e
fix igroups orientation
joostvanzwieten Jun 9, 2020
11f417d
fix tri, hull of empty Sample
joostvanzwieten Jun 9, 2020
4aa87da
WIP: fix flipping normal of manifold refs
joostvanzwieten May 14, 2020
fa9b380
fix prepare_eval with subsample.transforms=None
joostvanzwieten Jun 15, 2020
057b049
add boundary and interfaces to empty topology
joostvanzwieten Jun 15, 2020
111e2bb
make Topology.integrate_elementwise tensorial
joostvanzwieten Jun 16, 2020
e43627f
add CompressedSample, CompressedTopology
joostvanzwieten Jun 16, 2020
362145e
update
joostvanzwieten Jun 16, 2020
099c6e3
revert ProductTopology.basis simplifications
joostvanzwieten Jun 16, 2020
b09c924
move normal, grad, dotnorm above Namespace
joostvanzwieten Jun 9, 2020
6b5e75d
add {append,prepend}axes helper functions
joostvanzwieten Jun 6, 2020
11acf2d
add Pointwise.outer constructor
joostvanzwieten Jun 8, 2020
94746ed
don't verify existence of func during expr parsing
joostvanzwieten Jun 5, 2020
c75701b
use summation convention for func calls
joostvanzwieten Jun 6, 2020
debb180
allow n as function in expressions
joostvanzwieten Jun 9, 2020
2c4cf8b
add `d(func, geom, ...)` as alt syntax for derivs
joostvanzwieten Jun 8, 2020
e384cbf
add `n(x_i)` as alt syntax for normal
joostvanzwieten Jun 9, 2020
2a18910
support user-defined functions in `Namespace`
joostvanzwieten Jun 8, 2020
87c81eb
support grad to nd geom
joostvanzwieten Jun 9, 2020
e9ad4c2
support normal of nd geom
joostvanzwieten Jun 9, 2020
a7831da
add Levi-Civita symbol
joostvanzwieten Jun 10, 2020
9ec5551
update examples to d(func, geom), n(geom) syntax
joostvanzwieten Jun 10, 2020
9b1d847
deprecate [f]_i and [f]_x_i expression syntax
joostvanzwieten Jun 16, 2020
6e2d55f
deprecate grad, deriv, normals with explicit geom
joostvanzwieten Jun 16, 2020
2c1214c
extend support for TensorPoints.tri
joostvanzwieten Jun 30, 2020
0d36635
fix
joostvanzwieten Jul 10, 2020
0973d67
restore multidimensional slicing of tensor topos
joostvanzwieten Jul 13, 2020
77952ce
impl TensorPoints.basis
joostvanzwieten Jul 14, 2020
4259762
support TensorPoints.tri with points2.ndims=1
joostvanzwieten Jul 14, 2020
6bf212b
add support for line segments in export.vtk
CVerhoosel May 8, 2020
cc56ad0
fix typo
joostvanzwieten Jul 22, 2020
8a4ae7c
implement Element.__bool__
joostvanzwieten Jan 7, 2020
bf06b47
inherit groups in HierarchicalTopology.interfaces
joostvanzwieten Mar 25, 2020
7361898
add DisjointUnion.basis
joostvanzwieten Jan 7, 2020
5ff9d44
add function.WithTransformsBasis
joostvanzwieten Jan 7, 2020
55634b0
add topology.WithIdentifierTopology
joostvanzwieten Jan 7, 2020
7380aa1
WIP: partition
joostvanzwieten Dec 16, 2019
d2a4ca6
support alternate root name in partition
joostvanzwieten Apr 16, 2021
3021591
prune gmsh periodic table of nonexisting vertices
gertjanvanzwieten Sep 23, 2020
1aaf319
skip gmsh edge elements with no adjacent area
gertjanvanzwieten Sep 23, 2020
92ada06
remove unused vnodes and tidy up
gertjanvanzwieten Sep 23, 2020
a2ccd39
refactor parsegmsh to support meshio < and >=4.3.1
gertjanvanzwieten Oct 15, 2020
bdd429b
fixes
joostvanzwieten May 18, 2021
21a144b
make tol a mandatory argument for locate
gertjanvanzwieten Apr 29, 2020
480ff67
add weights argument to locate
gertjanvanzwieten Jul 5, 2020
1d7b802
remove locate args ischeme and scale, add maxdist
gertjanvanzwieten Dec 10, 2020
38dbbce
parallelize Topology.trim
joostvanzwieten May 24, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/notes/binary_operations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ Binary Operations on Arrays

1. In the above table the summation axes are numbered backward. For example, ``sum(-1)`` is used to sum over the last axis of an array. Although forward numbering is possible in many situations, backward numbering is generally preferred in Nutils code.
2. When a summation over multiple axes is performed (#6), these axes are to be listed. In the case of single-axis summations listing is optional (for example ``sum(-1)`` is equivalent to ``sum([-1])``). The shorter notation ``sum(-1)`` is preferred.
3. When the numer of dimensions of the two arguments of a binary operation mismatch, singleton axes are automatically prepended to the "shorter" argument. This property can be used to shorten notation. For example, #3 can be written as ``(A*b).sum(-1)``. To avoid ambiguities, in general, such abbreviations are discouraged.
3. When the number of dimensions of the two arguments of a binary operation mismatch, singleton axes are automatically prepended to the "shorter" argument. This property can be used to shorten notation. For example, #3 can be written as ``(A*b).sum(-1)``. To avoid ambiguities, in general, such abbreviations are discouraged.
18 changes: 9 additions & 9 deletions docs/tutorial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ Note that discretization inevitably implies approximation, i.e. :math:`u ≠
space of piecewise linears, which contains the exact solution. We therefore
expect our Finite Element solution to be exact.

Wetting your appetite
---------------------
Whetting your appetite
----------------------

The computation can be set up in about 20 lines of Nutils code, including
visualization. The entire script is presented below, in copy-pasteable form
Expand Down Expand Up @@ -123,7 +123,7 @@ size between 0 and 1 is generated by

.. console::
>>> nutils.mesh.rectilinear([[0, 0.25, 0.5, 0.75, 1.0]])
(StructuredTopology<4>, Array<1>)
(StructuredLine<4>, Array<1>)

Alternatively we could have used :func:`numpy.linspace` to generate a sequence
of equidistant vertices, and unpack the resulting tuple:
Expand All @@ -142,7 +142,7 @@ is generated by

.. console::
>>> nutils.mesh.rectilinear([numpy.linspace(0, 1, 5), numpy.linspace(0, 1, 9)])
(StructuredTopology<4x8>, Array<2>)
(StructuredLine<4>*StructuredLine<8>, Array<2>)

Any topology defines a boundary via the :attr:`Topology.boundary
<nutils.topology.Topology.boundary>` attribute. Optionally, a topology can
Expand All @@ -152,7 +152,7 @@ dimension, making the left boundary accessible as:

.. console::
>>> topo.boundary['left']
StructuredTopology<>
PointsTopology<1>

Optionally, a topology can be made periodic in one or more dimensions by
passing a list of dimension indices to be periodic via the keyword argument
Expand All @@ -161,7 +161,7 @@ two-dimensional mesh periodic, add ``periodic=[1]``:

.. console::
>>> nutils.mesh.rectilinear([numpy.linspace(0, 1, 5), numpy.linspace(0, 1, 9)], periodic=[1])
(StructuredTopology<4x8p>, Array<2>)
(StructuredLine<4>*StructuredLine<8p>, Array<2>)

Note that in this case the boundary topology, though still available, is empty.

Expand All @@ -177,7 +177,7 @@ it helps to think of a basis as evaluating always to the full array.

Several :class:`~nutils.topology.Topology` objects support creating bases via
the :meth:`Topology.basis() <nutils.topology.Topology.basis>` method. A
:class:`~nutils.topology.StructuredTopology`, as generated by
:class:`~nutils.topology.StructuredLine`, as generated by
:func:`nutils.mesh.rectilinear`, can create a spline basis with arbitrary
degree and arbitrary continuity. The following generates a degree one spline
basis on our previously created unit line topology ``topo``:
Expand Down Expand Up @@ -609,7 +609,7 @@ The optimization problem can also be solved by the
.. console::
>>> nutils.solver.optimize('lhs', sqr)
optimize > solve > solving 5 dof system to machine precision using direct solver
optimize > solve > solver returned with residual 0e+00
optimize > solve > solver returned with residual 0e+00±1e-15
optimize > optimum value 0.00e+00±1e-15
array([0. , 0.25, 0.5 , 0.75, 1. ])±1e-15

Expand Down Expand Up @@ -676,7 +676,7 @@ second argument of :class:`Topology.sample()
.. console::
>>> bezier = topo.sample('bezier', 2)
>>> bezier
Sample<1D, 4 elems, 8 points>
UniformSample<1D, 4 elems, 8 points>

The resulting :class:`nutils.sample.Sample` object can be used to evaluate
:class:`~nutils.function.Array` functions via the :meth:`Sample.eval(func)
Expand Down
8 changes: 4 additions & 4 deletions examples/adaptivity.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ def main(etype:str, btype:str, degree:int, nrefine:int):
if irefine:
refdom = domain.refined
ns.refbasis = refdom.basis(btype, degree=degree)
indicator = refdom.integral('refbasis_n,k u_,k d:x' @ ns, degree=degree*2).eval(lhs=lhs)
indicator -= refdom.boundary.integral('refbasis_n u_,k n_k d:x' @ ns, degree=degree*2).eval(lhs=lhs)
indicator = refdom.integral('d(refbasis_n, x_k) d(u, x_k) d:x' @ ns, degree=degree*2).eval(lhs=lhs)
indicator -= refdom.boundary.integral('refbasis_n d(u, x_k) n(x_k) d:x' @ ns, degree=degree*2).eval(lhs=lhs)
supp = ns.refbasis.get_support(indicator**2 > numpy.mean(indicator**2))
domain = domain.refined_by(ns.refbasis.transforms[supp])

Expand All @@ -62,11 +62,11 @@ def main(etype:str, btype:str, degree:int, nrefine:int):
sqr = domain.boundary.integral('du^2 d:x' @ ns, degree=7)
cons = solver.optimize('lhs', sqr, droptol=1e-15, constrain=cons)

res = domain.integral('basis_n,k u_,k d:x' @ ns, degree=degree*2)
res = domain.integral('d(basis_n, x_k) d(u, x_k) d:x' @ ns, degree=degree*2)
lhs = solver.solve_linear('lhs', res, constrain=cons)

ndofs = len(ns.basis)
error = domain.integral('<du^2, du_,k du_,k>_i d:x' @ ns, degree=7).eval(lhs=lhs)**.5
error = domain.integral('<du^2, d(du, x_k) d(du, x_k)>_i d:x' @ ns, degree=7).eval(lhs=lhs)**.5
rate, offset = linreg.add(numpy.log(len(ns.basis)), numpy.log(error))
treelog.user('ndofs: {ndofs}, L2 error: {error[0]:.2e} ({rate[0]:.2f}), H1 error: {error[1]:.2e} ({rate[1]:.2f})'.format(ndofs=len(ns.basis), error=error, rate=rate))

Expand Down
10 changes: 5 additions & 5 deletions examples/burgers.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ def main(nelems:int, ndims:int, degree:int, timescale:float, newtontol:float, en
ns.f = '.5 u^2'
ns.C = 1

res = domain.integral('-basis_n,0 f d:x' @ ns, degree=5)
res += domain.interfaces.integral('-[basis_n] n_0 ({f} - .5 C [u] n_0) d:x' @ ns, degree=degree*2)
res = domain.integral('-d(basis_n, x_i) δ_i0 f d:x' @ ns, degree=5)
res += domain.interfaces.integral('-[basis_n] n(x_i) δ_i0 ({f} - .5 C [u] n(x_j) δ_j0) d:x' @ ns, degree=degree*2)
inertia = domain.integral('basis_n u d:x' @ ns, degree=5)

sqr = domain.integral('(u - exp(-?y_i ?y_i)(y_i = 5 (x_i - 0.5_i)))^2 d:x' @ ns, degree=5)
Expand Down Expand Up @@ -93,6 +93,6 @@ def test_1d_p2(self):
def test_2d_p1(self):
lhs = main(ndims=2, nelems=4, timescale=.1, degree=1, endtime=.01, newtontol=1e-5)
self.assertAlmostEqual64(lhs, '''
eNoNyKENhEAQRuGEQsCv2SEzyQZHDbRACdsDJNsBjqBxSBxBHIgJ9xsqQJ1Drro1L1/eYBZceGz8njrR
yacm8UQLBvPYCw1airpyUVYSJLhKijK4IC01WDnqqxvX8OTl427aU73sctPGr3qqceBnRzOjo0xy9JpJ
R73m6R6YMZo/Q+FCLQ==''')
eNoNx6ENhjAQBtCEQcDX9Mhd0uCYgRUYoTtAwga4P2gcEkcQUHGBzzABCoes+slTrzcT4hk0aDwn9ObA
bQcKHHig2x6oUFOWF1JIltdUIerMnXTuIzNHfXVhL5vbnJeFXy3h6aJVVrnIU4kdj20okUQaeuyOnxmR
otVWU4zf/jlhQi0=''')
4 changes: 2 additions & 2 deletions examples/cahnhilliard.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ def main(nelems:int, etype:str, btype:str, degree:int, epsilon:typing.Optional[f
ns.dt = timestep

nrg_mix = domain.integral('F d:x' @ ns, degree=7)
nrg_iface = domain.integral('.5 c_,k c_,k d:x' @ ns, degree=7)
nrg_iface = domain.integral('.5 d(c, x_k) d(c, x_k) d:x' @ ns, degree=7)
nrg_wall = domain.boundary.integral('(abs(ewall) + c ewall) d:x' @ ns, degree=7)
nrg = nrg_mix + nrg_iface + nrg_wall + domain.integral('(dF - m dc - .5 dt epsilon^2 m_,k m_,k) d:x' @ ns, degree=7)
nrg = nrg_mix + nrg_iface + nrg_wall + domain.integral('(dF - m dc - .5 dt epsilon^2 d(m, x_k) d(m, x_k)) d:x' @ ns, degree=7)

numpy.random.seed(seed)
lhs = numpy.random.normal(0, .5, ns.cbasis.shape) # initial condition
Expand Down
6 changes: 3 additions & 3 deletions examples/cylinderflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,9 @@ def main(nelems:int, degree:int, reynolds:float, rotation:float, timestep:float,
ns.ubasis_ni = 'unbasis_n J_i0 + utbasis_n J_i1' # piola transformation
ns.u_i = 'ubasis_ni ?lhs_n'
ns.p = 'pbasis_n ?lhs_n'
ns.sigma_ij = '(u_i,j + u_j,i) / Re - p δ_ij'
ns.sigma_ij = '(d(u_i, x_j) + d(u_j, x_i)) / Re - p δ_ij'
ns.N = 10 * degree / elemangle # Nitsche constant based on element size = elemangle/2
ns.nitsche_ni = '(N ubasis_ni - (ubasis_ni,j + ubasis_nj,i) n_j) / Re'
ns.nitsche_ni = '(N ubasis_ni - (d(ubasis_ni, x_j) + d(ubasis_nj, x_i)) n_j) / Re'
ns.rotation = rotation
ns.uwall_i = '0.5 rotation <-sin(phi), cos(phi)>_i'

Expand All @@ -75,7 +75,7 @@ def main(nelems:int, degree:int, reynolds:float, rotation:float, timestep:float,
numpy.random.seed(seed)
lhs0 *= numpy.random.normal(1, .1, lhs0.shape) # add small velocity noise

res = domain.integral('(ubasis_ni u_i,j u_j + ubasis_ni,j sigma_ij + pbasis_n u_k,k) d:x' @ ns, degree=9)
res = domain.integral('(ubasis_ni d(u_i, x_j) u_j + d(ubasis_ni, x_j) sigma_ij + pbasis_n d(u_k, x_k)) d:x' @ ns, degree=9)
res += domain.boundary['inner'].integral('(nitsche_ni (u_i - uwall_i) - ubasis_ni sigma_ij n_j) d:x' @ ns, degree=9)
inertia = domain.integral('ubasis_ni u_i d:x' @ ns, degree=9)

Expand Down
13 changes: 7 additions & 6 deletions examples/drivencavity-compatible.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,18 @@ def main(nelems:int, degree:int, reynolds:float):
ns.u_i = 'ubasis_ni ?lhs_n'
ns.p = 'pbasis_n ?lhs_n'
ns.l = 'lbasis_n ?lhs_n'
ns.stress_ij = '(u_i,j + u_j,i) / Re - p δ_ij'
ns.stress_ij = '(d(u_i, x_j) + d(u_j, x_i)) / Re - p δ_ij'
ns.uwall = domain.boundary.indicator('top'), 0
ns.N = 5 * degree * nelems # nitsche constant based on element size = 1/nelems
ns.nitsche_ni = '(N ubasis_ni - (ubasis_ni,j + ubasis_nj,i) n_j) / Re'
ns.nitsche_ni = '(N ubasis_ni - (d(ubasis_ni, x_j) + d(ubasis_nj, x_i)) n(x_j)) / Re'

res = domain.integral('(ubasis_ni,j stress_ij + pbasis_n (u_k,k + l) + lbasis_n p) d:x' @ ns, degree=2*degree)
res = domain.integral('(d(ubasis_ni, x_j) stress_ij + pbasis_n (d(u_k, x_k) + l) + lbasis_n p) d:x' @ ns, degree=2*degree)
res += domain.boundary.integral('(nitsche_ni (u_i - uwall_i) - ubasis_ni stress_ij n_j) d:x' @ ns, degree=2*degree)
with treelog.context('stokes'):
lhs0 = solver.solve_linear('lhs', res)
postprocess(domain, ns, lhs=lhs0)

res += domain.integral('ubasis_ni u_i,j u_j d:x' @ ns, degree=3*degree)
res += domain.integral('ubasis_ni d(u_i, x_j) u_j d:x' @ ns, degree=3*degree)
with treelog.context('navierstokes'):
lhs1 = solver.newton('lhs', res, lhs0=lhs0).solve(tol=1e-10)
postprocess(domain, ns, lhs=lhs1)
Expand All @@ -66,13 +66,14 @@ def main(nelems:int, degree:int, reynolds:float):

def postprocess(domain, ns, every=.05, spacing=.01, **arguments):

div = domain.integral('(u_k,k)^2 d:x' @ ns, degree=1).eval(**arguments)**.5
div = domain.integral('d(u_k, x_k)^2 d:x' @ ns, degree=1).eval(**arguments)**.5
treelog.info('velocity divergence: {:.2e}'.format(div)) # confirm that velocity is pointwise divergence-free

ns = ns.copy_() # copy namespace so that we don't modify the calling argument
ns.streambasis = domain.basis('std', degree=2)[1:] # remove first dof to obtain non-singular system
ns.stream = 'streambasis_n ?streamdofs_n' # stream function
sqr = domain.integral('((u_0 - stream_,1)^2 + (u_1 + stream_,0)^2) d:x' @ ns, degree=4)
ns.ε = function.levicivita(2)
sqr = domain.integral('(u_i - ε_ij d(stream, x_j)) (u_i - ε_ij d(stream, x_j)) d:x' @ ns, degree=4)
arguments['streamdofs'] = solver.optimize('streamdofs', sqr, arguments=arguments) # compute streamlines

bezier = domain.sample('bezier', 9)
Expand Down
9 changes: 5 additions & 4 deletions examples/drivencavity.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def main(nelems:int, etype:str, degree:int, reynolds:float):
])
ns.u_i = 'ubasis_ni ?lhs_n'
ns.p = 'pbasis_n ?lhs_n'
ns.stress_ij = '(u_i,j + u_j,i) / Re - p δ_ij'
ns.stress_ij = '(d(u_i, x_j) + d(u_j, x_i)) / Re - p δ_ij'

sqr = domain.boundary.integral('u_k u_k d:x' @ ns, degree=degree*2)
wallcons = solver.optimize('lhs', sqr, droptol=1e-15)
Expand All @@ -46,12 +46,12 @@ def main(nelems:int, etype:str, degree:int, reynolds:float):
cons = numpy.choose(numpy.isnan(lidcons), [lidcons, wallcons])
cons[-1] = 0 # pressure point constraint

res = domain.integral('(ubasis_ni,j stress_ij + pbasis_n u_k,k) d:x' @ ns, degree=degree*2)
res = domain.integral('(d(ubasis_ni, x_j) stress_ij + pbasis_n d(u_k, x_k)) d:x' @ ns, degree=degree*2)
with treelog.context('stokes'):
lhs0 = solver.solve_linear('lhs', res, constrain=cons)
postprocess(domain, ns, lhs=lhs0)

res += domain.integral('.5 (ubasis_ni u_i,j - ubasis_ni,j u_i) u_j d:x' @ ns, degree=degree*3)
res += domain.integral('.5 (ubasis_ni d(u_i, x_j) - d(ubasis_ni, x_j) u_i) u_j d:x' @ ns, degree=degree*3)
with treelog.context('navierstokes'):
lhs1 = solver.newton('lhs', res, lhs0=lhs0, constrain=cons).solve(tol=1e-10)
postprocess(domain, ns, lhs=lhs1)
Expand All @@ -67,7 +67,8 @@ def postprocess(domain, ns, every=.05, spacing=.01, **arguments):
ns = ns.copy_() # copy namespace so that we don't modify the calling argument
ns.streambasis = domain.basis('std', degree=2)[1:] # remove first dof to obtain non-singular system
ns.stream = 'streambasis_n ?streamdofs_n' # stream function
sqr = domain.integral('((u_0 - stream_,1)^2 + (u_1 + stream_,0)^2) d:x' @ ns, degree=4)
ns.ε = function.levicivita(2)
sqr = domain.integral('(u_i - ε_ij d(stream, x_j)) (u_i - ε_ij d(stream, x_j)) d:x' @ ns, degree=4)
arguments['streamdofs'] = solver.optimize('streamdofs', sqr, arguments=arguments) # compute streamlines

bezier = domain.sample('bezier', 9)
Expand Down
4 changes: 2 additions & 2 deletions examples/elasticity.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ def main(nelems:int, etype:str, btype:str, degree:int, poisson:float):
ns.X_i = 'x_i + u_i'
ns.lmbda = 2 * poisson
ns.mu = 1 - 2 * poisson
ns.strain_ij = '(u_i,j + u_j,i) / 2'
ns.strain_ij = '(d(u_i, x_j) + d(u_j, x_i)) / 2'
ns.stress_ij = 'lmbda strain_kk δ_ij + 2 mu strain_ij'

sqr = domain.boundary['left'].integral('u_k u_k d:x' @ ns, degree=degree*2)
sqr += domain.boundary['right'].integral('(u_0 - .5)^2 d:x' @ ns, degree=degree*2)
cons = solver.optimize('lhs', sqr, droptol=1e-15)

res = domain.integral('basis_ni,j stress_ij d:x' @ ns, degree=degree*2)
res = domain.integral('d(basis_ni, x_j) stress_ij d:x' @ ns, degree=degree*2)
lhs = solver.solve_linear('lhs', res, constrain=cons)

bezier = domain.sample('bezier', 5)
Expand Down
4 changes: 2 additions & 2 deletions examples/finitestrain.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def main(nelems:int, etype:str, btype:str, degree:int, poisson:float, angle:floa
ns.ubasis = domain.basis(btype, degree=degree).vector(2)
ns.u_i = 'ubasis_ki ?lhs_k'
ns.X_i = 'x_i + u_i'
ns.strain_ij = '.5 (u_i,j + u_j,i)'
ns.strain_ij = '.5 (d(u_i, x_j) + d(u_j, x_i))'
ns.energy = 'lmbda strain_ii strain_jj + 2 mu strain_ij strain_ij'

sqr = domain.boundary['left'].integral('u_k u_k d:x' @ ns, degree=degree*2)
Expand All @@ -58,7 +58,7 @@ def main(nelems:int, etype:str, btype:str, degree:int, poisson:float, angle:floa
X, energy = bezier.eval(['X_i', 'energy'] @ ns, lhs=lhs0)
export.triplot('linear.png', X, energy, tri=bezier.tri, hull=bezier.hull)

ns.strain_ij = '.5 (u_i,j + u_j,i + u_k,i u_k,j)'
ns.strain_ij = '.5 (d(u_i, x_j) + d(u_j, x_i) + d(u_k, x_i) d(u_k, x_j))'
ns.energy = 'lmbda strain_ii strain_jj + 2 mu strain_ij strain_ij'

energy = domain.integral('energy d:x' @ ns, degree=degree*2)
Expand Down
4 changes: 2 additions & 2 deletions examples/laplace.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,13 @@ def main(nelems:int, etype:str, btype:str, degree:int):
# We are now ready to implement the Laplace equation. In weak form, the
# solution is a scalar field :math:`u` for which:
#
# .. math:: ∀ v: ∫_Ω v_{,k} u_{,k} - ∫_{Γ_n} v f = 0.
# .. math:: ∀ v: ∫_Ω \frac{dv}{dx_i} \frac{du}{dx_i} - ∫_{Γ_n} v f = 0.
#
# By linearity the test function :math:`v` can be replaced by the basis that
# spans its space. The result is an integral ``res`` that evaluates to a
# vector matching the size of the function space.

res = domain.integral('basis_n,i u_,i d:x' @ ns, degree=degree*2)
res = domain.integral('d(basis_n, x_i) d(u, x_i) d:x' @ ns, degree=degree*2)
res -= domain.boundary['right'].integral('basis_n cos(1) cosh(x_1) d:x' @ ns, degree=degree*2)

# The Dirichlet constraints are set by finding the coefficients that minimize
Expand Down
6 changes: 3 additions & 3 deletions examples/platewithhole-nurbs.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def main(nrefine:int, traction:float, radius:float, poisson:float):
ns.ubasis = nurbsbasis.vector(2)
ns.u_i = 'ubasis_ni ?lhs_n'
ns.X_i = 'x_i + u_i'
ns.strain_ij = '(u_i,j + u_j,i) / 2'
ns.strain_ij = '(d(u_i, x_j) + d(u_j, x_i)) / 2'
ns.stress_ij = 'lmbda strain_kk δ_ij + 2 mu strain_ij'
ns.r2 = 'x_k x_k'
ns.R2 = radius**2 / ns.r2
Expand All @@ -74,7 +74,7 @@ def main(nrefine:int, traction:float, radius:float, poisson:float):
cons = solver.optimize('lhs', sqr, droptol=1e-15, constrain=cons)

# construct residual
res = domain.integral('ubasis_ni,j stress_ij d:x' @ ns, degree=9)
res = domain.integral('d(ubasis_ni, x_j) stress_ij d:x' @ ns, degree=9)

# solve system
lhs = solver.solve_linear('lhs', res, constrain=cons)
Expand All @@ -85,7 +85,7 @@ def main(nrefine:int, traction:float, radius:float, poisson:float):
export.triplot('stressxx.png', X, stressxx, tri=bezier.tri, hull=bezier.hull, clim=(numpy.nanmin(stressxx), numpy.nanmax(stressxx)))

# evaluate error
err = domain.integral('<du_k du_k, du_i,j du_i,j>_n d:x' @ ns, degree=9).eval(lhs=lhs)**.5
err = domain.integral('<du_k du_k, d(du_i, x_j) d(du_i, x_j)>_n d:x' @ ns, degree=9).eval(lhs=lhs)**.5
treelog.user('errors: L2={:.2e}, H1={:.2e}'.format(*err))

return err, cons, lhs
Expand Down
6 changes: 3 additions & 3 deletions examples/platewithhole.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def main(nelems:int, etype:str, btype:str, degree:int, traction:float, maxrefine
ns.ubasis = domain.basis(btype, degree=degree).vector(2)
ns.u_i = 'ubasis_ni ?lhs_n'
ns.X_i = 'x_i + u_i'
ns.strain_ij = '(u_i,j + u_j,i) / 2'
ns.strain_ij = '(d(u_i, x_j) + d(u_j, x_i)) / 2'
ns.stress_ij = 'lmbda strain_kk δ_ij + 2 mu strain_ij'
ns.r2 = 'x_k x_k'
ns.R2 = radius**2 / ns.r2
Expand All @@ -59,14 +59,14 @@ def main(nelems:int, etype:str, btype:str, degree:int, traction:float, maxrefine
sqr = domain.boundary['top,right'].integral('du_k du_k d:x' @ ns, degree=20)
cons = solver.optimize('lhs', sqr, droptol=1e-15, constrain=cons)

res = domain.integral('ubasis_ni,j stress_ij d:x' @ ns, degree=degree*2)
res = domain.integral('d(ubasis_ni, x_j) stress_ij d:x' @ ns, degree=degree*2)
lhs = solver.solve_linear('lhs', res, constrain=cons)

bezier = domain.sample('bezier', 5)
X, stressxx = bezier.eval(['X_i', 'stress_00'] @ ns, lhs=lhs)
export.triplot('stressxx.png', X, stressxx, tri=bezier.tri, hull=bezier.hull)

err = domain.integral('<du_k du_k, du_i,j du_i,j>_n d:x' @ ns, degree=max(degree,3)*2).eval(lhs=lhs)**.5
err = domain.integral('<du_k du_k, d(du_i, x_j) d(du_i, x_j)>_n d:x' @ ns, degree=max(degree,3)*2).eval(lhs=lhs)**.5
treelog.user('errors: L2={:.2e}, H1={:.2e}'.format(*err))

return err, cons, lhs
Expand Down
Loading