def IndicatorSmoothed(self, lsets, eps=0.03): """ Indicator CoefficientFunction, indicating the eps-region around the instances' region (codim>0). We assume that the level sets are approximately signed distance functions in the eps region of the zero set. Parameters ---------- lsets : tuple(ngsolve.CoefficientFunctions) The set of level set functions defining the region. eps : float The distance around the sub-domain which is indicated (default eps=0.01). Returns ------- CoefficientFunction 1 in the region of distance eps around the sub-domain, 0 else. """ if self.codim == 0: print("Warning: IndicatorSmothed is not intended for codim==0! " "Please use the Indicator method") return self.Indicator(lsets) def gf_abs(gf): return IfPos(gf, gf, -gf) ind_combined = CoefficientFunction(0) for dtt in self.as_list: ind = CoefficientFunction(1) ind_cut = CoefficientFunction(1) for i, dt in enumerate(dtt): if dt == IF: ind *= IfPos(gf_abs(lsets[i]) - eps, 0, 1) elif dt == POS: ind_cut *= IfPos(lsets[i] - eps, 1, 0) elif dt == NEG: ind_cut *= IfPos(-lsets[i] + eps, 1, 0) ind_combined += ind * ind_cut del ind, ind_cut ind_leveled = IfPos(ind_combined, 1, 0) del ind_combined return ind_leveled
def DrawDiscontinuous_std(StdDraw, levelset, fneg, fpos, *args, **kwargs): def StdDrawWithDummyScene(cf, *args, **kwargs): StdDraw(cf, *args, **kwargs) return dummy_scene if "deformation" in kwargs and StdDraw.__module__ == "ngsolve.solve": args2 = list(args[:]) args2[1] = "deformation_" + args[1] StdDraw(kwargs["deformation"], *tuple(args2), **kwargs) visoptions.deformation = 1 if not "sd" in kwargs: kwargs["sd"] = 5 return StdDrawWithDummyScene(IfPos(levelset, fpos, fneg), *args, **kwargs)
def Indicator(self, lsets): """ Indicator CoefficientFunction for a DomainTypeArray of codim=0. Parameters ---------- lsets : tuple(ngsolve.CoefficientFunctions) The set of level set functions with respect to which the instances' region is defined. Returns ------- CoefficientFunction 1 in the region on interest, 0 else. """ if self.codim != 0: print("Warning: Indicator is not intended for codim > 0! " "Please use the IndicatorSmoothed method") return self.IndicatorSmoothed(lsets) ind_combined = CoefficientFunction(0) for dtt in self.as_list: ind = CoefficientFunction(1) for i, dt in enumerate(dtt): if dt == POS: ind *= IfPos(lsets[i], 1, 0) elif dt == NEG: ind *= IfPos(-lsets[i], 1, 0) ind_combined += ind del ind ind_leveled = IfPos(ind_combined, 1, 0) del ind_combined return ind_leveled
def tanh( x: Union[int, float, Parameter, CoefficientFunction] ) -> Union[float, CoefficientFunction]: """ Function that implements the hyperbolic tangent in a way that's compatible with NGSolve Parameter and Coefficient objects. Args: x: The value to evaluate tanh at. Return: ~: tanh(x) """ # Deal with some math overflow problems if type(x) is Parameter or type(x) is CoefficientFunction: # Added to ensure that the tanh calculation does not return nan x_adj = IfPos(x - 350, 350, x) else: # float or int if x > 350: x_adj = 350 else: x_adj = x return (exp(2 * x_adj) - 1.0) / (exp(2 * x_adj) + 1.0)
def gf_abs(gf): return IfPos(gf, gf, -gf)
def Heat1DFEM(N=8, order=1, k1=1, k2=1, Q1=0, Q2=10, boundary_condition_left="Robin", boundary_condition_right="Dirichlet", value_left=0, value_right=1, q_value_left=0, q_value_right=1, r_value_left=0, r_value_right=1, intervalsize=0.14): if (boundary_condition_left == "Neumann" or (boundary_condition_left == "Robin" and r_value_left == 0)) and ( boundary_condition_right == "Neumann" or (boundary_condition_right == "Robin" and r_value_right == 0)): print("Temperatur ist nicht eindeutig bestimmt.") #return mesh1D = Mesh1D(N, interval=(0, intervalsize)) dbnds = [] if boundary_condition_left == "Dirichlet": dbnds.append(1) # print(True) if boundary_condition_right == "Dirichlet": dbnds.append(2) fes = H1(mesh1D, order=order, dirichlet=dbnds) gf = GridFunction(fes) if boundary_condition_left == "Dirichlet": gf.vec[0] = value_left if boundary_condition_right == "Dirichlet": gf.vec[N] = value_right Q = IfPos(X - 0.5 * intervalsize, Q2, Q1) k = IfPos(X - 0.5 * intervalsize, k2, k1) u, v = fes.TnT() a = BilinearForm(fes) a += SymbolicBFI(k * grad(u) * grad(v)) if boundary_condition_left == "Robin": a += SymbolicBFI(r_value_left * u * v, definedon=mesh1D.Boundaries("left")) if boundary_condition_right == "Robin": a += SymbolicBFI(r_value_right * u * v, definedon=mesh1D.Boundaries("right")) a.Assemble() f = LinearForm(fes) f += SymbolicLFI(Q * v) f.Assemble() if boundary_condition_left == "Neumann": f.vec[0] += q_value_left elif boundary_condition_left == "Robin": f.vec[0] += r_value_left * value_left if boundary_condition_right == "Neumann": f.vec[N] += q_value_right elif boundary_condition_right == "Robin": f.vec[N] += r_value_right * value_right f.vec.data -= a.mat * gf.vec gf.vec.data += a.mat.Inverse(fes.FreeDofs()) * f.vec Draw1D(mesh1D, [(gf, "u_h")], n_p=5 * order**2)