def pml_local_op(self, w): sub_e, sub_h, sub_p, sub_q = self.split_ehpq(w) e_subset = self.get_eh_subset()[0:3] h_subset = self.get_eh_subset()[3:6] dim_subset = (True, ) * self.dimensions + (False, ) * (3 - self.dimensions) def pad_vec(v, subset): result = numpy.zeros((3, ), dtype=object) result[numpy.array(subset, dtype=bool)] = v return result from grudge.symbolic import make_sym_vector sig = pad_vec(make_sym_vector("sigma", self.dimensions), dim_subset) sig_prime = pad_vec(make_sym_vector("sigma_prime", self.dimensions), dim_subset) if self.add_decay: tau = pad_vec(make_sym_vector("tau", self.dimensions), dim_subset) else: tau = numpy.zeros((3, )) e = pad_vec(sub_e, e_subset) h = pad_vec(sub_h, h_subset) p = pad_vec(sub_p, dim_subset) q = pad_vec(sub_q, dim_subset) rhs = numpy.zeros(12, dtype=object) for mx in range(3): my = (mx + 1) % 3 mz = (mx + 2) % 3 from grudge.tools.mathematics import levi_civita assert levi_civita((mx, my, mz)) == 1 rhs[mx] += -sig[my] / self.epsilon * ( 2 * e[mx] + p[mx]) - 2 * tau[my] / self.epsilon * e[mx] rhs[my] += -sig[mx] / self.epsilon * ( 2 * e[my] + p[my]) - 2 * tau[mx] / self.epsilon * e[my] rhs[3 + mz] += 1 / (self.epsilon * self.mu) * (sig_prime[mx] * q[mx] - sig_prime[my] * q[my]) rhs[6 + mx] += sig[my] / self.epsilon * e[mx] rhs[6 + my] += sig[mx] / self.epsilon * e[my] rhs[9 + mx] += -sig[mx] / self.epsilon * q[mx] - (e[my] + e[mz]) from grudge.tools import full_to_subset_indices sub_idx = full_to_subset_indices(e_subset + h_subset + dim_subset + dim_subset) return rhs[sub_idx]
def apply_diff_tensor(v): if isinstance(self.diffusion_tensor, np.ndarray): sym_diff_tensor = self.diffusion_tensor else: sym_diff_tensor = (make_sym_vector("diffusion", self.dimensions**2).reshape( self.dimensions, self.dimensions)) return np.dot(sym_diff_tensor, v)
def sym_operator(self, w=None): from grudge.tools import count_subset fld_cnt = count_subset(self.get_eh_subset()) if w is None: from grudge.symbolic import make_sym_vector w = make_sym_vector("w", fld_cnt + 2 * self.dimensions) from grudge.tools import join_fields return join_fields(MaxwellOperator.sym_operator(self, w[:fld_cnt]), numpy.zeros((2 * self.dimensions, ), dtype=object)) + self.pml_local_op(w)
def sym_operator(self): from grudge.mesh import BTAG_ALL from grudge.symbolic import make_sym_vector, BoundaryPair, \ get_flux_operator, make_nabla, InverseMassOperator nabla = make_nabla(self.dimensions) m_inv = InverseMassOperator() v = make_sym_vector("v", self.arg_count) bc = make_sym_vector("bc", self.arg_count) local_op_result = 0 idx = 0 for i, i_enabled in enumerate(self.subset): if i_enabled and i < self.dimensions: local_op_result += nabla[i] * v[idx] idx += 1 flux_op = get_flux_operator(self.flux()) return local_op_result - m_inv( flux_op(v) + flux_op(BoundaryPair(v, bc, BTAG_ALL)))
def f_bar(self): from grudge.symbolic import make_sym_vector return make_sym_vector("f_bar", len(self.method))