SubdomainFacetBasis
implementation, how do I...
#860
Replies: 5 comments 27 replies
-
Here are some ideas: In [1]: from skfem import *
In [2]: m = MeshTri().refined(3)
In [3]: tind = m.elements_satisfying(lambda x: (x[0] - 0.5) ** 2 + (x[1] - 0.5)
...: **2 < 0.25**2)
In [4]: tind
Out[4]:
array([ 7, 9, 11, 18, 20, 22, 31, 39, 54, 62, 63, 71, 73,
75, 82, 84, 86, 94, 103, 105, 107, 114, 116, 118, 126, 127])
In [6]: import numpy as np
In [7]: all_facets, counts = np.unique(m.t2f[:, tind], return_counts=True)
In [9]: facets = all_facets[counts == 1] # facets on subdomain boundary?
In [10]: m.f2t[:, facets] # triangles on both sides of subdomain boundary?
Out[10]:
array([[ 82, 62, 84, 94, 89, 31, 91, 55, 50, 41, 52, 43, 126,
95],
[ 90, 70, 92, 78, 73, 47, 75, 63, 114, 105, 116, 107, 30,
127]]) Finally you check if first or second row is in the given |
Beta Was this translation helpful? Give feedback.
-
My take on this is here: #861 |
Beta Was this translation helpful? Give feedback.
-
Looking now at your code. What is |
Beta Was this translation helpful? Give feedback.
-
Is mesh.f2t[:, facets].flatten('F') equivalent to mesh.f2t[:, facets].T.reshape(-1) just more efficient? Edit: A = np.empty([2000,400,200])
%time a = A.T.reshape(-1)
%time b = A.flatten('F')
(a==b).all()
|
Beta Was this translation helpful? Give feedback.
-
I see, so the way you intend this to work is that super().__init__(
mesh,
elem,
mapping=mapping,
intorder=intorder,
quadrature=quadrature,
# the next three arguments are 1d array of the same length.
facets=facets, # this first one specifies which facets are in the basis
_tind=_tind, # this one specifies which triangle to use for the trace values
_tind_normals=_tind, # this one specifies which triangle to point the normal out of
dofs=dofs,
) Edit: the comments were wrong, but they're correct now. |
Beta Was this translation helpful? Give feedback.
-
SubdomainFacetBasis is supposed to give you at least a
P1
(but ideally any) Basis on a set of facets comprising an internal boundary of the domain. (Facets on the exterior boundary aren't allowed.) The normals are supposed to be consistently outward. To do this I'm subclassingBoundaryFacetBasis
and there are three important steps I'm needing help figuring out. (1) I have working, but its hacky. (2) is working and probably okay. (3) is just broken and I don't know how to fix it. Here they are:1. How to get the facets on the boundary.
If the boundary is defined by a zero/one indicator function (1 in a cell , then facets with discontinuous traces are on the boundary and the rest aren't. I used
asm
to make this happen. As a by-product, the sign of the difference of these traces indicates the whether theskfem
normal is "inward" or "outward", so you can just multiply this difference with theself.normals
and they'll all get pointed the right way (outward). This method is robust, does not require contiguous subdomains and automatically excludes actual boundary facets.However, it uses
asm
andFunctional
. This creates an import loop, so that's bad. It is also not really the purpose ofasm
. On the other hand, this works. So I feel like getting rid ofasm
and doing it right is going to involve rewriting mesh traversal code that already exists and that I don't know how to write. This is the main reason I wondered in a different discussion if a formal iterator is something we should have.Nevertheless, this implementation works, in that it does found the subdomain boundary and which facets need to be "flipped".
2. Flipping the normals.
Since in the previous step I ended up with an array of integers that are
1
for already correct normals and-1
for normals pointing the wrong way, "fixing" the normals was as easy asExcept this broke after #849. A work around here is to insist
But I want to make sure this is in the spirit of the changes in #849. It seems like all the things in
DiscreteField
are the result of linear operations and at least scalar multiplication and addition should be supported because they can just be applied to everything.Also I wonder if
ufunc(DiscreteField, array)
andufunc(DiscreteField, DiscreteField)
should returnDiscreteField
with the extra attribute stripped?3. How to I get the right trace values?
Here is where the implementation is just broken. I know which trace needs to be used on which facet. I thought I could write
But it didn't seem to work, and I'm not too sure what is
tind
,f2t
, orAffineMapping
.... these things are getting way down in the guts of implementation. I think this is another reason for the formal iterator I mention earlier, but the biggest reason why I don't write that myself: I'm not even sure where to start. It might be that this idea of iteration is just me not understanding what some of the lower level functions do. There names are pretty terse. I'll try to add some docstrings in #851 too.Beta Was this translation helpful? Give feedback.
All reactions