82 kc = np.where(G.solid, ks, kf)
83 I =
lambda c: (c[0] % n) * n + (c[1] % n)
84 S =
System(n * n); col = []
86 sh = np.array((1, 0)
if axis == 0
else (0, 1))
89 P = (i, j); Q = (i + sh[0], j + sh[1])
90 Pw = (P[0] % n, P[1] % n); Qw = (Q[0] % n, Q[1] % n)
91 sP, sQ = G.solid[Pw], G.solid[Qw]
92 a_s = G.asx[i + 1, j]
if axis == 0
else G.asy[i, j + 1]
93 pP = G.pos(P); fpt = pP + 0.5 * h * sh
94 nrm = fpt -
center_of(fpt); nrm /= np.hypot(*nrm); nx2 = nrm[axis] ** 2
95 if min(abs(G.s[Pw]), abs(G.s[Qw])) > 1.5 * h:
96 ts = np.array([0.0, 1.0]); sv = np.array([G.s[Pw], G.s[Qw]])
98 ts = np.linspace(0, 1, 129); sv = np.array([
sdf(pP + t * h * sh, G.R)
for t
in ts])
99 cr = np.nonzero(sv[:-1] * sv[1:] < 0)[0]
102 kk = kf + (ks - kf) * a_s * (1 - nx2)
if not sP
else ks + (kf - ks) * (1 - a_s) * (1 - nx2)
105 st = [(P, -kk), (Q, kk)]
107 Pm = (P[0] - sh[0], P[1] - sh[1]); Qp = (Q[0] + sh[0], Q[1] + sh[1])
108 simple = (len(cr) == 1
and G.solid[Pm[0] % n, Pm[1] % n] == sP
and G.solid[Qp[0] % n, Qp[1] % n] == sQ)
110 k_ = cr[0]; t0 = ts[k_] + (ts[k_ + 1] - ts[k_]) * sv[k_] / (sv[k_] - sv[k_ + 1])
111 gl, gr = dir_face_both(t0 - 0.5)
112 fP = a_s
if sP
else 1 - a_s
113 w = kc[Pw] * fP * gl + kc[Qw] * (1 - fP) * gr
114 st = [(Pm, w[0]), (P, w[1]), (Q, w[2]), (Qp, w[3])]
117 kk = (kf + (ks - kf) * a_s * (1 - nx2)) / (1 + (kf / ks - 1) * ls * nx2)
118 st = [(P, -kk), (Q, kk)]
121 S.add(I(P), I(c), wv / h**2, xc); S.add(I(Q), I(c), -wv / h**2, xc)
122 if axis == 0
and i == n - 1:
125 T =
lambda c: th[I(c)] - G.pos(c)[0]
126 return sum(-sum(wv * T(c)
for c, wv
in st) / h * h
for st
in col)
131 fi = (p[0] - G.x0) / h - 0.5; fj = (p[1] - G.y0) / h - 0.5
132 i0, j0 = int(np.floor(fi)), int(np.floor(fj)); tx, ty = fi - i0, fj - j0
133 cand = [(i0, j0), (i0 + 1, j0), (i0, j0 + 1), (i0 + 1, j0 + 1)]
134 ww = [(1 - tx) * (1 - ty), tx * (1 - ty), (1 - tx) * ty, tx * ty]
135 ok = [valid[c[0] % n, c[1] % n]
for c
in cand]
136 ws = sum(w
for w, o
in zip(ww, ok)
if o)
137 if ws < 0.5:
return None,
False
138 return [(c, w / ws)
for c, w, o
in zip(cand, ww, ok)
if o],
not all(ok)
141def k_P2F(G, kf, ks, gapaware=False, c=0.7):
146 def touched(ax_, ay_):
147 t = (ax_[1:, :] > 0) | (ax_[:-1, :] > 0) | (ay_[:, 1:] > 0) | (ay_[:, :-1] > 0)
149 vf = (kfr > 1e-12) | touched(1 - G.asx, 1 - G.asy)
150 vs = (G.ks > 1e-12) | touched(G.asx, G.asy)
151 idf = -np.ones((n, n), int); idf[vf] = np.arange(vf.sum())
152 ids = -np.ones((n, n), int); ids[vs] = vf.sum() + np.arange(vs.sum())
153 N = vf.sum() + vs.sum()
155 If =
lambda cc: idf[cc[0] % n, cc[1] % n]; Is =
lambda cc: ids[cc[0] % n, cc[1] % n]
157 for (Ix, D, ax_, ay_, valid)
in ((If, kf, 1 - G.asx, 1 - G.asy, vf), (Is, ks, G.asx, G.asy, vs)):
159 sh = (1, 0)
if axis == 0
else (0, 1)
162 a = ax_[i + 1, j]
if axis == 0
else ay_[i, j + 1]
163 P = (i, j); Q = (i + sh[0], j + sh[1])
164 if a <= 0
or Ix(P) < 0
or Ix(Q) < 0:
continue
166 for (cc, wv)
in ((P, -cf), (Q, cf)):
168 S.add(Ix(P), Ix(cc), wv, xc); S.add(Ix(Q), Ix(cc), -wv, xc)
169 if axis == 0
and i == n - 1:
170 col.append((Ix, D * a, P, Q))
171 Ax = -(G.asx[1:, :] - G.asx[:-1, :]) * h; Ay = -(G.asy[:, 1:] - G.asy[:, :-1]) * h
172 Aw = np.hypot(Ax, Ay)
173 stats = dict(fallback=0, inside_other=0)
174 for i, j
in zip(*np.nonzero(Aw > 1e-12 * h)):
175 if idf[i, j] < 0
or ids[i, j] < 0:
continue
176 p0 = G.pos((i, j)); cc =
center_of(p0); nn = (p0 - cc) / np.hypot(*(p0 - cc)); xw = cc + G.R * nn
179 ts = np.linspace(1e-4, 3 * h, 300)
180 hit = [t
for t
in ts
if sdf(xw + t * nn, G.R) < 0
and np.hypot(*(xw + t * nn - cc)) > G.R + 1e-12]
181 if hit: sf_max = min(sf_max, 0.5 * hit[0])
183 for sf
in (sf_max, 1.0 * h, 1.5 * h):
184 pf, fb =
bilin(G, If, xw + sf * nn, vf)
185 if pf
is not None:
break
186 if sdf(xw + sf * nn, G.R) < 0: stats[
"inside_other"] += 1
187 for ss
in (c * h, 1.0 * h, 1.5 * h):
188 ps, fb2 =
bilin(G, Is, xw - ss * nn, vs)
189 if ps
is not None:
break
190 stats[
"fallback"] += int(fb) + int(fb2)
191 gf, gs = kf / sf, ks / ss
192 g = gf * gs / (gf + gs)
199 S.add(idf[i, j], If(cc_), -A * g * wv, x_); S.add(ids[i, j], If(cc_), +A * g * wv, x_)
202 S.add(idf[i, j], Is(cc_), +A * g * wv, x_); S.add(ids[i, j], Is(cc_), -A * g * wv, x_)
205 for (Ix, ka, P, Q)
in col:
206 TP = th[Ix(P)] - G.pos(P)[0]; TQ = th[Ix(Q)] - G.pos(Q)[0]
207 q += -ka * (TQ - TP) / h * h