def test_calculus_2d_4(): DIM = 2 domain = Domain('Omega', dim=DIM) V = ScalarFunctionSpace('V', domain, kind=None) u, v = elements_of(V, names='u, v') a = Constant('a', is_real=True) # ... jump operator assert (jump(u + v) == jump(u) + jump(v)) assert (jump(a * u) == a * jump(u)) # ... # ... avg operator assert (avg(u + v) == avg(u) + avg(v)) assert (avg(a * u) == a * avg(u)) # ... # ... Dn operator assert (Dn(u + v) == Dn(u) + Dn(v)) assert (Dn(a * u) == a * Dn(u)) # ... # ... minus operator assert (minus(u + v) == minus(u) + minus(v)) assert (minus(a * u) == a * minus(u)) # ... # ... plus operator assert (plus(u + v) == plus(u) + plus(v)) assert (plus(a * u) == a * plus(u))
def test_interface_2d_1(): # ... def two_patches(): from sympde.topology import InteriorDomain from sympde.topology import Connectivity, Interface A = Square('A') B = Square('B') A = A.interior B = B.interior connectivity = Connectivity() bnd_A_1 = Boundary(r'\Gamma_1', A, axis=0, ext=-1) bnd_A_2 = Boundary(r'\Gamma_2', A, axis=0, ext=1) bnd_A_3 = Boundary(r'\Gamma_3', A, axis=1, ext=-1) bnd_A_4 = Boundary(r'\Gamma_4', A, axis=1, ext=1) bnd_B_1 = Boundary(r'\Gamma_1', B, axis=0, ext=-1) bnd_B_2 = Boundary(r'\Gamma_2', B, axis=0, ext=1) bnd_B_3 = Boundary(r'\Gamma_3', B, axis=1, ext=-1) bnd_B_4 = Boundary(r'\Gamma_4', B, axis=1, ext=1) connectivity['I'] = Interface('I', bnd_A_2, bnd_B_1) Omega = Domain('Omega', interiors=[A, B], boundaries=[ bnd_A_1, bnd_A_2, bnd_A_3, bnd_A_4, bnd_B_1, bnd_B_2, bnd_B_3, bnd_B_4 ], connectivity=connectivity) return Omega # ... # create a domain with an interface domain = two_patches() interfaces = domain.interfaces V = ScalarFunctionSpace('V', domain) u, v = elements_of(V, names='u, v') print(integral(interfaces, u * v)) expr = integral(domain, dot(grad(v), grad(u))) expr += integral(interfaces, -avg(Dn(u)) * jump(v) + avg(Dn(v)) * jump(u)) a = BilinearForm((u, v), expr) print(a)
def test_interface_integral_1(): # ... A = Square('A') B = Square('B') domain = A.join(B, name='domain', bnd_minus=A.get_boundary(axis=0, ext=1), bnd_plus=B.get_boundary(axis=0, ext=-1)) # ... x, y = domain.coordinates V = ScalarFunctionSpace('V', domain, kind=None) assert (V.is_broken) u, v = elements_of(V, names='u, v') # ... I = domain.interfaces # ... # expr = minus(Dn(u)) # print(expr) # import sys; sys.exit(0) # ... bilinear forms # a = BilinearForm((u,v), integral(domain, u*v)) # a = BilinearForm((u,v), integral(domain, dot(grad(u),grad(v)))) # a = BilinearForm((u,v), integral(I, jump(u) * jump(v))) # a = BilinearForm((u,v), integral(I, jump(Dn(u)) * jump(v))) # a = BilinearForm((u,v), integral(domain, dot(grad(u),grad(v))) # + integral(I, jump(u) * jump(v))) # Nitsch kappa = Constant('kappa') expr_I = (-jump(u) * jump(Dn(v)) + kappa * jump(u) * jump(v) + plus(Dn(u)) * minus(v) + minus(Dn(u)) * plus(v)) a = BilinearForm( (u, v), integral(domain, dot(grad(u), grad(v))) + integral(I, expr_I)) # # TODO BUG # bnd_A = A.get_boundary(axis=0, ext=1) # # a = BilinearForm((u,v), integral(domain, dot(grad(u),grad(v))) # + integral(I, jump(u) * jump(v)) # + integral(bnd_A, dx(u)*v)) expr = TerminalExpr(a) print(expr)
def test_interface_integral_3(): # ... A = Square('A') B = Square('B') C = Square('C') AB = A.join(B, name='AB', bnd_minus=A.get_boundary(axis=0, ext=1), bnd_plus=B.get_boundary(axis=0, ext=-1)) domain = AB.join(C, name='domain', bnd_minus=B.get_boundary(axis=0, ext=1), bnd_plus=C.get_boundary(axis=0, ext=-1)) # ... x, y = domain.coordinates V = ScalarFunctionSpace('V', domain, kind=None) assert (V.is_broken) u, v = elements_of(V, names='u, v') # ... I = domain.interfaces # print(I) # print(integral(I, jump(u) * jump(v))) # a = BilinearForm((u,v), integral(domain, u*v)) # a = BilinearForm((u,v), integral(domain, dot(grad(u),grad(v)))) # a = BilinearForm((u,v), integral(I, jump(u) * jump(v))) a = BilinearForm((u, v), integral(domain, dot(grad(u), grad(v))) + integral(I, jump(u) * jump(v))) expr = TerminalExpr(a) print(expr) # ... # ... linear forms b = LinearForm( v, integral(domain, sin(x + y) * v) + integral(I, cos(x + y) * jump(v))) expr = TerminalExpr(b) print(expr)
def test_interface_integral_2(): # ... A = Square('A') B = Square('B') domain = A.join(B, name='domain', bnd_minus=A.get_boundary(axis=0, ext=1), bnd_plus=B.get_boundary(axis=0, ext=-1)) # ... x, y = domain.coordinates V = ScalarFunctionSpace('V', domain, kind=None) assert (V.is_broken) u, u1, u2, u3 = elements_of(V, names='u, u1, u2, u3') v, v1, v2, v3 = elements_of(V, names='v, v1, v2, v3') # ... I = domain.interfaces a = BilinearForm((u, v), integral(domain, dot(grad(u), grad(v)))) b = BilinearForm((u, v), integral(I, jump(u) * jump(v))) A = BilinearForm(((u1, u2), (v1, v2)), a(u1, v1) + a(u2, v2) + b(u1, v1) + b(u2, v2) + b(u1, v2)) B = BilinearForm( ((u1, u2, u3), (v1, v2, v3)), a(u1, v1) + a(u2, v2) + a(u3, v3) + b(u1, v1) + b(u2, v2) + b(u1, v2)) print(TerminalExpr(A)) print(TerminalExpr(B)) # ... # ... linear forms b = LinearForm(v, integral(I, jump(v))) b = LinearForm((v1, v2), b(v1) + b(v2)) expr = TerminalExpr(b) print(expr)
def _split_expr_over_interface(expr, interface, tests=None, trials=None): """ Splits an expression defined on an interface, into expressions where the test and trial functions are defined on each side of the interface. Parameters: expr: sympde expression interface: interface of a connectivity tests: tests functions as given from linear or bilinear forms trials: trials functions as given from linear or bilinear forms Returns: sympde expression """ # ... is_bilinear = not (trials is None) and not (tests is None) is_linear = (trials is None) and not (tests is None) if trials is None: trials = [] if tests is None: tests = [] # ... int_expressions = {} bnd_expressions = {} # ... # we replace all jumps jumps = expr.atoms(Jump) args = [j._args[0] for j in jumps] for a in args: expr = expr.subs({jump(a): minus(a) - plus(a)}) # ... # ... d_trials = {} for u in trials: u_minus = minus(u) u_plus = plus(u) d_trials[u] = {'-': u_minus, '+': u_plus} # # TODO add sub for avg # expr = expr.subs({jump(u): u_minus - u_plus}) d_tests = {} for v in tests: v_minus = minus(v) v_plus = plus(v) d_tests[v] = {'-': v_minus, '+': v_plus} # # TODO add sub for avg # expr = expr.subs({jump(v): v_minus - v_plus}) # ... # ... trials = [] for u in d_trials.keys(): u_minus = d_trials[u]['-'] u_plus = d_trials[u]['+'] trials += [u_minus, u_plus] tests = [] for u in d_tests.keys(): u_minus = d_tests[u]['-'] u_plus = d_tests[u]['+'] tests += [u_minus, u_plus] # ... # ... def _nullify(expr, u, us): """nullifies all symbols in us except u.""" others = list(set(us) - set([u])) for other in others: expr = expr.subs({other: 0}) return expr # ... if is_bilinear: for u in d_trials.keys(): for v in d_tests.keys(): u_minus = d_trials[u]['-'] u_plus = d_trials[u]['+'] v_minus = d_tests[v]['-'] v_plus = d_tests[v]['+'] # ... newexpr = _nullify(expr, u_minus, trials) newexpr = _nullify(newexpr, v_minus, tests) newexpr = newexpr.subs({u_minus: u, v_minus: v}) mapping = newexpr.atoms(InterfaceMapping) if mapping and not is_zero(newexpr): mapping = list(mapping)[0] newexpr = newexpr.subs(mapping, mapping.minus) if not is_zero(newexpr): if interface.minus in bnd_expressions: newexpr += bnd_expressions[interface.minus] bnd_expressions[interface.minus] = newexpr.subs( interface, interface.minus) # ... newexpr = _nullify(expr, u_plus, trials) newexpr = _nullify(newexpr, v_plus, tests) newexpr = newexpr.subs({u_plus: u, v_plus: v}) mapping = newexpr.atoms(InterfaceMapping) if mapping and not is_zero(newexpr): mapping = list(mapping)[0] newexpr = newexpr.subs(mapping, mapping.plus) for nn in newexpr.atoms(NormalVector): newexpr = newexpr.subs(nn, -nn) if not is_zero(newexpr): if interface.plus in bnd_expressions: newexpr += bnd_expressions[interface.plus] bnd_expressions[interface.plus] = newexpr.subs( interface, interface.plus) # ... # TODO must call InterfaceExpression afterward newexpr = _nullify(expr, u_minus, trials) newexpr = _nullify(newexpr, v_plus, tests) mapping = newexpr.atoms(InterfaceMapping) if mapping: mapping = list(mapping)[0] for det in newexpr.atoms(SymbolicDeterminant): if det.atoms(InterfaceMapping): newdet = det.subs(mapping, mapping.minus) newexpr = newexpr.subs(det, newdet) if not is_zero(newexpr): if isinstance(u, IndexedVectorFunction): u_minus = minus(u.base) if isinstance(v, IndexedVectorFunction): v_plus = plus(v.base) if (u_minus, v_plus) in int_expressions: newexpr += int_expressions[u_minus, v_plus].expr int_expressions[u_minus, v_plus] = InterfaceExpression( interface, u_minus, v_plus, newexpr) # ... # TODO must call InterfaceExpression afterward newexpr = _nullify(expr, u_plus, trials) newexpr = _nullify(newexpr, v_minus, tests) mapping = newexpr.atoms(InterfaceMapping) if mapping: mapping = list(mapping)[0] for det in newexpr.atoms(SymbolicDeterminant): if det.atoms(InterfaceMapping): newdet = det.subs(mapping, mapping.minus) newexpr = newexpr.subs(det, newdet) if not is_zero(newexpr): if isinstance(u, IndexedVectorFunction): u_plus = plus(u.base) if isinstance(v, IndexedVectorFunction): v_minus = minus(v.base) if (u_plus, v_minus) in int_expressions: newexpr += int_expressions[u_plus, v_minus].expr int_expressions[u_plus, v_minus] = InterfaceExpression( interface, u_plus, v_minus, newexpr) elif is_linear: for v in d_tests.keys(): v_minus = d_tests[v]['-'] v_plus = d_tests[v]['+'] # ... newexpr = _nullify(expr, v_minus, tests) newexpr = newexpr.subs({v_minus: v}) mapping = newexpr.atoms(InterfaceMapping) if mapping: mapping = list(mapping)[0] newexpr = newexpr.subs(mapping, mapping.minus) if not is_zero(newexpr): if interface.minus in bnd_expressions: newexpr += bnd_expressions[interface.minus] bnd_expressions[interface.minus] = newexpr # ... # ... newexpr = _nullify(expr, v_plus, tests) newexpr = newexpr.subs({v_plus: v}) mapping = newexpr.atoms(InterfaceMapping) if mapping: mapping = list(mapping)[0] newexpr = newexpr.subs(mapping, mapping.plus) if not is_zero(newexpr): if interface.plus in bnd_expressions: newexpr += bnd_expressions[interface.plus] bnd_expressions[interface.plus] = newexpr # ... int_expressions = list(int_expressions.values()) return int_expressions, bnd_expressions
def _split_expr_over_interface(expr, interface, tests=None, trials=None): """ Splits an expression defined on an interface, into expressions where the test and trial functions are defined on each side of the interface. Parameters: expr: sympde expression interface: interface of a connectivity tests: tests functions as given from linear or bilinear forms trials: trials functions as given from linear or bilinear forms Returns: sympde expression """ # ... def _new_atom(v, label): new = '{v}_{label}'.format(v=v.name, label=label) return element_of(v.space, name=new) # ... # ... is_bilinear = not (trials is None) and not (tests is None) is_linear = (trials is None) and not (tests is None) if trials is None: trials = [] if tests is None: tests = [] # ... # ... B_minus = interface.minus B_plus = interface.plus boundaries = (B_minus, B_plus) labels = ('minus', 'plus') # ... int_expressions = [] bnd_expressions = {} # ... # we replace all jumps jumps = expr.atoms(Jump) args = [j._args[0] for j in jumps] for a in args: expr = expr.subs({jump(a): minus(a) - plus(a)}) # ... # ... d_trials = {} for u in trials: u_minus = minus(u) u_plus = plus(u) d_trials[u] = {'-': u_minus, '+': u_plus} # # TODO add sub for avg # expr = expr.subs({jump(u): u_minus - u_plus}) d_tests = {} for v in tests: v_minus = minus(v) v_plus = plus(v) d_tests[v] = {'-': v_minus, '+': v_plus} # # TODO add sub for avg # expr = expr.subs({jump(v): v_minus - v_plus}) expr = expand(expr) # ... # ... trials = [] for u in d_trials.keys(): u_minus = d_trials[u]['-'] u_plus = d_trials[u]['+'] trials += [u_minus, u_plus] tests = [] for u in d_tests.keys(): u_minus = d_tests[u]['-'] u_plus = d_tests[u]['+'] tests += [u_minus, u_plus] # ... # ... def _nullify(expr, u, us): """nullifies all symbols in us except u.""" others = list(set(us) - set([u])) for other in others: expr = expr.subs({other: 0}) return expr # ... # ... def _not_zero_matrix(M): n, m = expr.shape return any([M[i, j] != 0 for i, j in product(range(n), range(m))]) # ... # ... if is_bilinear: for u in d_trials.keys(): u_minus = d_trials[u]['-'] u_plus = d_trials[u]['+'] for v in d_tests.keys(): v_minus = d_tests[v]['-'] v_plus = d_tests[v]['+'] # ... newexpr = _nullify(expr, u_minus, trials) newexpr = _nullify(newexpr, v_minus, tests) newexpr = newexpr.subs({u_minus: u, v_minus: v}) if _not_zero_matrix(newexpr): bnd_expressions[interface.minus] = newexpr # ... # ... # TODO must call InterfaceExpression afterward newexpr = _nullify(expr, u_minus, trials) newexpr = _nullify(newexpr, v_plus, tests) if _not_zero_matrix(newexpr): int_expressions += [ InterfaceExpression(interface, newexpr) ] # ... # ... # TODO must call InterfaceExpression afterward newexpr = _nullify(expr, u_plus, trials) newexpr = _nullify(newexpr, v_minus, tests) if _not_zero_matrix(newexpr): int_expressions += [ InterfaceExpression(interface, newexpr) ] # ... # ... newexpr = _nullify(expr, u_plus, trials) newexpr = _nullify(newexpr, v_plus, tests) newexpr = newexpr.subs({u_plus: u, v_plus: v}) if _not_zero_matrix(newexpr): bnd_expressions[interface.plus] = newexpr # ... elif is_linear: for v in d_tests.keys(): v_minus = d_tests[v]['-'] v_plus = d_tests[v]['+'] # ... newexpr = _nullify(expr, v_minus, tests) newexpr = newexpr.subs({v_minus: v}) if _not_zero_matrix(newexpr): bnd_expressions[interface.minus] = newexpr # ... # ... newexpr = _nullify(expr, v_plus, tests) newexpr = newexpr.subs({v_plus: v}) if _not_zero_matrix(newexpr): bnd_expressions[interface.plus] = newexpr # ... # ... return int_expressions, bnd_expressions
def _split_expr_over_interface(expr, interface, tests=None, trials=None): """ Splits an expression defined on an interface, into expressions where the test and trial functions are defined on each side of the interface. Parameters: expr: sympde expression interface: interface of a connectivity tests: tests functions as given from linear or bilinear forms trials: trials functions as given from linear or bilinear forms Returns: sympde expression """ # ... is_bilinear = not (trials is None) and not (tests is None) is_linear = (trials is None) and not (tests is None) if trials is None: trials = [] if tests is None: tests = [] # ... int_expressions = [] bnd_expressions = OrderedDict() # ... # we replace all jumps jumps = expr.atoms(Jump) args = [j._args[0] for j in jumps] for a in args: expr = expr.subs({jump(a): minus(a) - plus(a)}) # ... # ... d_trials = OrderedDict() for u in trials: u_minus = minus(u) u_plus = plus(u) d_trials[u] = {'-': u_minus, '+': u_plus} # # TODO add sub for avg # expr = expr.subs({jump(u): u_minus - u_plus}) d_tests = OrderedDict() for v in tests: v_minus = minus(v) v_plus = plus(v) d_tests[v] = {'-': v_minus, '+': v_plus} # # TODO add sub for avg # expr = expr.subs({jump(v): v_minus - v_plus}) # ... # ... trials = [] for u in d_trials.keys(): u_minus = d_trials[u]['-'] u_plus = d_trials[u]['+'] trials += [u_minus, u_plus] tests = [] for u in d_tests.keys(): u_minus = d_tests[u]['-'] u_plus = d_tests[u]['+'] tests += [u_minus, u_plus] # ... # ... def _nullify(expr, u, us): """nullifies all symbols in us except u.""" others = list(set(us) - set([u])) for other in others: expr = expr.subs({other: 0}) return expr # ... if is_bilinear: for u in d_trials.keys(): u_minus = d_trials[u]['-'] u_plus = d_trials[u]['+'] for v in d_tests.keys(): v_minus = d_tests[v]['-'] v_plus = d_tests[v]['+'] # ... newexpr = _nullify(expr, u_minus, trials) newexpr = _nullify(newexpr, v_minus, tests) newexpr = newexpr.subs({u_minus: u, v_minus: v}) mapping = newexpr.atoms(InterfaceMapping) if mapping and not newexpr.is_zero: mapping = list(mapping)[0] newexpr = newexpr.subs(mapping, mapping.minus) if not newexpr.is_zero: bnd_expressions[interface.minus] = newexpr # ... # TODO must call InterfaceExpression afterward newexpr = _nullify(expr, u_minus, trials) newexpr = _nullify(newexpr, v_plus, tests) mapping = newexpr.atoms(InterfaceMapping) if mapping: mapping = list(mapping)[0] newexpr = newexpr.subs(mapping, mapping.plus) if not newexpr.is_zero: int_expressions += [ InterfaceExpression(interface, u_minus, v_plus, newexpr) ] # ... # TODO must call InterfaceExpression afterward newexpr = _nullify(expr, u_plus, trials) newexpr = _nullify(newexpr, v_minus, tests) mapping = newexpr.atoms(InterfaceMapping) if mapping: mapping = list(mapping)[0] newexpr = newexpr.subs(mapping, mapping.plus) if not newexpr.is_zero: int_expressions += [ InterfaceExpression(interface, u_plus, v_minus, newexpr) ] # ... newexpr = _nullify(expr, u_plus, trials) newexpr = _nullify(newexpr, v_plus, tests) newexpr = newexpr.subs({u_plus: u, v_plus: v}) mapping = newexpr.atoms(InterfaceMapping) if mapping: mapping = list(mapping)[0] newexpr = newexpr.subs(mapping, mapping.plus) if not newexpr.is_zero: bnd_expressions[interface.plus] = newexpr # ... elif is_linear: for v in d_tests.keys(): v_minus = d_tests[v]['-'] v_plus = d_tests[v]['+'] # ... newexpr = _nullify(expr, v_minus, tests) newexpr = newexpr.subs({v_minus: v}) mapping = newexpr.atoms(InterfaceMapping) if mapping: mapping = list(mapping)[0] newexpr = newexpr.subs(mapping, mapping.minus) if not newexpr.is_zero: bnd_expressions[interface.minus] = newexpr # ... # ... newexpr = _nullify(expr, v_plus, tests) newexpr = newexpr.subs({v_plus: v}) mapping = newexpr.atoms(InterfaceMapping) if mapping: mapping = list(mapping)[0] newexpr = newexpr.subs(mapping, mapping.plus) if not newexpr.is_zero: bnd_expressions[interface.plus] = newexpr # ... return int_expressions, bnd_expressions