def TimeSlider_DrawDC(cf1,cf2,cf3,mesh,*args,**kwargs): """ Draw a (reference) time-dependent function that is discontinuous across an interface described by a level set function. Change reference time through widget slider. Args: cf1 (CoefficientFunction): level set function cf2 (CoefficientFunction): function to draw where lset is negative cf3 (CoefficientFunction): function to draw where lset is positive mesh (Mesh): Mesh Returns: widget element that allows to vary the reference time. """ DrawDC = MakeDiscontinuousDraw(Draw) if not isinstance(cf1,CoefficientFunction): cf1=CoefficientFunction(cf1) if not isinstance(cf2,CoefficientFunction): cf2=CoefficientFunction(cf2) if not isinstance(cf3,CoefficientFunction): cf3=CoefficientFunction(cf3) ts = Parameter(0) scene = DrawDC(fix_tref(cf1,ts),fix_tref(cf2,ts),fix_tref(cf3,ts),mesh,*args,**kwargs); def UpdateTime(time): ts.Set(time); scene.Redraw() return interact(UpdateTime,time=FloatSlider(description="tref:", continuous_update=False, min=0,max=1,step=.025))
def DrawDiscontinuous_webgui(WebGuiDraw,levelset, fneg, fpos, *args, **kwargs): fneg = CoefficientFunction(fneg) fpos = CoefficientFunction(fpos) if fneg.dim > 1 or fpos.dim > 1: print("webgui discontinuous vis only for scalar functions a.t.m., switching to IfPos variant") else: return WebGuiDraw(CoefficientFunction((levelset,fpos,fneg,0)),eval_function="value.x>0.0?value.y:value.z",*args,**kwargs) return DrawDiscontinuous_std(WebGuiDraw,levelset, fneg, fpos, *args, **kwargs)
def waveD(n, z, cwave): # Return action of boundary matrix Dn on z if len(z) == 2: return CoefficientFunction((n[1] * z[0] - cwave * n[0] * z[1], n[1] * z[1] - cwave * n[0] * z[0])) elif len(z) == 3: return CoefficientFunction( (n[2] * z[0] - cwave * n[0] * z[2], n[2] * z[1] - cwave * n[1] * z[2], n[2] * z[2] - cwave * n[0] * z[0] - cwave * n[1] * z[1])) else: raise ValueError('Boundary operator given vector of length %d' % len(z))
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 waveA(u, cwave): # Return action of the first order wave operator on u if len(u) == 2: q, mu = u dxq, dtq = ngs.grad(q) dxmu, dtmu = ngs.grad(mu) return CoefficientFunction((dtq - cwave * dxmu, dtmu - cwave * dxq)) elif len(u) == 3: q1, q2, mu = u dxq1, dyq1, dtq1 = ngs.grad(q1) dxq2, dyq2, dtq2 = ngs.grad(q2) dxmu, dymu, dtmu = ngs.grad(mu) return CoefficientFunction((dtq1 - cwave * dxmu, dtq2 - cwave * dymu, dtmu - cwave * dxq1 - cwave * dyq2)) else: raise ValueError('Wave operator cannot act on vectors of length %d' % len(u))
def TimeSlider_Draw(cf,mesh,*args,**kwargs): ts = Parameter(0) if not isinstance(cf,CoefficientFunction): cf = CoefficientFunction(cf) scene = Draw(fix_tref(cf,ts),mesh,*args,**kwargs); def UpdateTime(time): ts.Set(time); scene.Redraw() return interact(UpdateTime,time=FloatSlider(description="tref:", continuous_update=False, min=0,max=1,step=.025))
def avg(q: CoefficientFunction) -> CoefficientFunction: """ Returns the average of a scalar field. Args: q (CoefficientFunction): The scalar field. Returns: ~ (CoefficientFunction): The average of q at every facet of the mesh. """ return 0.5 * (q + q.Other())
def jump(q: CoefficientFunction) -> CoefficientFunction: """ Returns the jump of a field. Args: q: The field. Returns: ~: The jump of q at every facet of the mesh. """ return q - q.Other()
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 kappa(mesh,lset_approx, subdivlvl=0): """ Tuple of ratios between negative/positive and full part of an element (deprecated). """ print("kappa-function is deprecated - use CutRatioGF instead") kappa1 = GridFunction(L2(mesh,order=0)) lset_neg = { "levelset" : lset_approx, "domain_type" : NEG, "subdivlvl" : subdivlvl} kappa_f = LinearForm(kappa1.space) kappa_f += SymbolicLFI(levelset_domain = lset_neg, form = kappa1.space.TestFunction() ) kappa_f.Assemble(); kappa1.space.SolveM(CoefficientFunction(1.0),kappa_f.vec) kappa1.vec.data = kappa_f.vec kappa2 = 1.0 - kappa1 return (kappa1,kappa2)
def grad_avg(q: CoefficientFunction) -> CoefficientFunction: """ Returns the average of the gradient of a field. Args: q: The field. Returns: ~: The average of the gradient of q at every facet of the mesh. """ # Grad must be called differently if q is a trial or testfunction instead of a coefficientfunction/gridfunction. if isinstance(q, ProxyFunction): return 0.5 * (Grad(q) + Grad(q.Other())) else: return 0.5 * (Grad(q) + Grad(q).Other())
def SpaceTimeSet(self, cf, *args, **kwargs): """ Overrides the NGSolve version of Set in case of a space-time FESpace. In this case the usual Set() is used on each nodal dof in time. """ if (isinstance(self.space, CSpaceTimeFESpace)): cf = CoefficientFunction(cf) gfs = GridFunction(self.space.spaceFES) ndof_node = len(gfs.vec) j = 0 for i, ti in enumerate(self.space.TimeFE_nodes()): if self.space.IsTimeNodeActive(i): ngsolveSet(gfs, fix_tref(cf, ti), *args, **kwargs) self.vec[j * ndof_node:(j + 1) * ndof_node].data = gfs.vec[:] j += 1 else: ngsolveSet(self, cf, *args, **kwargs)
def discretize_ngsolve(): from ngsolve import (ngsglobals, Mesh, H1, CoefficientFunction, LinearForm, SymbolicLFI, BilinearForm, SymbolicBFI, grad, TaskManager) from netgen.csg import CSGeometry, OrthoBrick, Pnt import numpy as np ngsglobals.msg_level = 1 geo = CSGeometry() obox = OrthoBrick(Pnt(-1, -1, -1), Pnt(1, 1, 1)).bc("outer") b = [] b.append( OrthoBrick(Pnt(-1, -1, -1), Pnt(0.0, 0.0, 0.0)).mat("mat1").bc("inner")) b.append( OrthoBrick(Pnt(-1, 0, -1), Pnt(0.0, 1.0, 0.0)).mat("mat2").bc("inner")) b.append( OrthoBrick(Pnt(0, -1, -1), Pnt(1.0, 0.0, 0.0)).mat("mat3").bc("inner")) b.append( OrthoBrick(Pnt(0, 0, -1), Pnt(1.0, 1.0, 0.0)).mat("mat4").bc("inner")) b.append( OrthoBrick(Pnt(-1, -1, 0), Pnt(0.0, 0.0, 1.0)).mat("mat5").bc("inner")) b.append( OrthoBrick(Pnt(-1, 0, 0), Pnt(0.0, 1.0, 1.0)).mat("mat6").bc("inner")) b.append( OrthoBrick(Pnt(0, -1, 0), Pnt(1.0, 0.0, 1.0)).mat("mat7").bc("inner")) b.append( OrthoBrick(Pnt(0, 0, 0), Pnt(1.0, 1.0, 1.0)).mat("mat8").bc("inner")) box = (obox - b[0] - b[1] - b[2] - b[3] - b[4] - b[5] - b[6] - b[7]) geo.Add(box) for bi in b: geo.Add(bi) # domain 0 is empty! mesh = Mesh(geo.GenerateMesh(maxh=0.3)) # H1-conforming finite element space V = H1(mesh, order=NGS_ORDER, dirichlet="outer") v = V.TestFunction() u = V.TrialFunction() # Coeff as array: variable coefficient function (one CoefFct. per domain): sourcefct = CoefficientFunction([1 for i in range(9)]) with TaskManager(): # the right hand side f = LinearForm(V) f += SymbolicLFI(sourcefct * v) f.Assemble() # the bilinear-form mats = [] coeffs = [[0, 1, 0, 0, 0, 0, 0, 0, 1], [0, 0, 1, 0, 0, 0, 0, 1, 0], [0, 0, 0, 1, 0, 0, 1, 0, 0], [0, 0, 0, 0, 1, 1, 0, 0, 0]] for c in coeffs: diffusion = CoefficientFunction(c) a = BilinearForm(V, symmetric=False) a += SymbolicBFI(diffusion * grad(u) * grad(v), definedon=(np.where(np.array(c) == 1)[0] + 1).tolist()) a.Assemble() mats.append(a.mat) from pymor.bindings.ngsolve import NGSolveVectorSpace, NGSolveMatrixOperator, NGSolveVisualizer space = NGSolveVectorSpace(V) op = LincombOperator( [NGSolveMatrixOperator(m, space, space) for m in mats], [ ProjectionParameterFunctional('diffusion', (len(coeffs), ), (i, )) for i in range(len(coeffs)) ]) h1_0_op = op.assemble([1] * len(coeffs)).with_(name='h1_0_semi') F = space.zeros() F._list[0].real_part.impl.vec.data = f.vec F = VectorOperator(F) return StationaryModel(op, F, visualizer=NGSolveVisualizer(mesh, V), products={'h1_0_semi': h1_0_op}, parameter_space=CubicParameterSpace( op.parameter_type, 0.1, 1.))
def vec(listfun): return CoefficientFunction(tuple(f for f in listfun))
if example[3:] == 'triangular': mesh = ngs.Mesh(unit_square.GenerateMesh(maxh=h0)) elif example[3:] == 'rectangular': mesh = ngs.Mesh( unit_square.GenerateMesh(maxh=h0, quad_dominated=True)) q_zero = 'bottom' # mesh boundary parts where q = 0, mu_zero = 'bottom|right|left' # where mu = 0. x = ngs.x t = ngs.y cwave = 1 f = 2 * pi * pi * sin(pi * x) * cos(2 * pi * t) + pi * pi * sin( pi * x) * sin(pi * t) * sin(pi * t) F = CoefficientFunction((0, f)) exactu = CoefficientFunction( (pi * cos(pi * x) * sin(pi * t) * sin(pi * t), pi * sin(pi * x) * sin(2 * pi * t))) hs = [] er = [] for l in range(maxr): h = h0 * 2**(-l) hs.append(h) e, *rest = solvewavedirect(mesh, p, F, q_zero, mu_zero, cwave, exactu) # e, *rest = solvewave(mesh, p, F, q_zero, mu_zero, cwave, exactu) er.append(e) mesh.Refine()