Пример #1
0
def SpaceTimeWeakSet(gfu_e, cf, space_fes):
    """
Ondocumented feature
    """
    gfu_e_repl = GridFunction(space_fes)
    gfu_e_repl.Set(cf)
    gfu_e.vec[:].data = gfu_e_repl.vec
Пример #2
0
def PartialApproximateWithFESpace(N=64, order=3, f="sin(3·pi·x)", j=2):

    i = j

    if f == "sin(3·pi·x)":
        f = Sin(3 * pi * X)
    elif f == "sin(3·pi·x)·cos(5·pi·x)":
        f = Sin(3 * pi * X) * Cos(5 * pi * X)
    else:
        print("no function provided")
        return

    mesh1D = Mesh1D(N)
    try:
        f(mesh1D(0.5))
    except:
        print("expression for f not valid!")
        return

    fes = H1(mesh1D, order=order)

    if (i > fes.ndof):
        print("j is too large. Setting j = ", fes.ndof - 1)
        i = fes.ndof

    gf = GridFunction(fes)
    gf.Set(f)
    for j in range(i, fes.ndof):
        gf.vec[j] = 0
    Draw1D(mesh1D, [(gf, "FE Approximation"), (f, "exakte Funktion")], n_p=20)
    for j in range(i):
        print("{:5.2f}".format(gf.vec[j]), end=" ")
        if (j > 0 and j % 18 == 17):
            print("")
Пример #3
0
def ApproximateWithFESpace(N=64, order=3, f="sin(3·pi·x)"):

    if f == "sin(3·pi·x)":
        f = Sin(3 * pi * X)
    elif f == "sin(3·pi·x)·cos(5·pi·x)":
        f = Sin(3 * pi * X) * Cos(5 * pi * X)
    else:
        print("no function provided")
        return

    mesh1D = Mesh1D(N)
    try:
        f(mesh1D(0.5))
    except:
        print("expression for f not valid!")
        return

    fes = H1(mesh1D, order=order)
    gf = GridFunction(fes)
    gf.Set(f)
    Draw1D(mesh1D, [(gf, "FE Approximation"), (f, "exakte Funktion")], n_p=20)
    for i in range(fes.ndof):
        print("{:5.2f}".format(gf.vec[i]), end=" ")
        if (i > 0 and i % 18 == 17):
            print("")
Пример #4
0
def create_and_load_gridfunction_from_file(filename: str,
                                           fes: FESpace) -> GridFunction:
    """
    Function to create a gridfunction and load the contents of a file into it.

    The gridfunction will be constructed from the same finite element space that the file data is assumed to come from.
    The file data must also fit the exact same dimensions and number of components as the given finite element space.

    NOTE: It is assumed that the gridfunction in the file is from the same FES and mesh as the one passed in,
          there is no way for the code to check.

    NOTE: If the FES and mesh are not the same, NGSolve will not necesarily crash,
          it will instead silently return garbage.

    Args:
        filename: File to load.
        fes: The finite element space the file data was created for.

    Returns:
        gfu: A gridfunction containing the values from the file
    """

    # Check that the file exists.
    if not os.path.isfile(filename):
        raise FileNotFoundError(
            'The file \"{}\" does not exist.'.format(filename))

    # Load gridfunction from file.
    gfu = GridFunction(fes)
    gfu.Load(filename)

    return gfu
Пример #5
0
def dxtref(mesh, order=None, time_order=-1, **kwargs):
    """
    Differential symbol for the integration over all elements extruded by
    the reference interval [0,1] to space-time prisms.

    Parameters
    ----------
    mesh : ngsolve.Mesh
        The spatial mesh.
        The domain type of interest.
    order : int
        Modify the order of the integration rule used.
    definedon : Region
        Domain description on where the integrator is defined.
    vb : {VOL, BND, BBND}
        Integration on domains volume or boundary. Default: VOL
        (if combined with skeleton VOL means interior facets,
                                   BND means boundary facets)
    element_boundary : bool
        Integration on each element boundary. Default: False
    element_vb : {VOL, BND, BBND}
        Integration on each element or its (B)boundary. Default: VOL
        (is overwritten by element_boundary if element_boundary 
        is True)
    skeleton : bool
        Integration over element-interface. Default: False.
    deformation : ngsolve.GridFunction
        Mesh deformation. Default: None.
    definedonelements : ngsolve.BitArray
        Allows integration only on elements or facets (if skeleton=True)
        that are marked True. Default: None.
    time_order : int
        Order in time that is used in the space-time integration.
        Default: time_order=-1 means that no space-time rule will be
        applied. This is only relevant for space-time discretizations.

    Return
    ------
        CutDifferentialSymbol(VOL)
    """
    tFE = ScalarTimeFE(1)
    STFES = tFE*H1(mesh)
    gflset = GridFunction(STFES)  
    gflset.vec[:] = 1
    for i in range(gflset.space.ndof):
        gflset.vec[i] = i+1


    lsetdom = {"levelset": gflset, "domain_type": POS}
    if order is not None:
        if type(order) != int:
            raise Exception("dxtref: order is not an integer! use keyword arguments for vb=VOL/BND.")
        lsetdom["order"] = order
    if type(time_order) != int:
        raise Exception("dxtref: time_order is not an integer! use keyword arguments for vb=VOL/BND.")
    if time_order > -1:
        lsetdom["time_order"] = time_order

    return _dCut_raw(lsetdom, **kwargs)
Пример #6
0
 def __init__(self, mesh=None, levelset=None):
     self.deform = GridFunction(H1(mesh, order=1, dim=mesh.dim), "dummy_deform")
     self.deform.vec.data[:] = 0.0
     if levelset != None:
         if mesh == None:
             raise Exception("need mesh")
         self.lset_p1 = GridFunction(H1(mesh, order=1))
         InterpolateToP1(levelset, self.lset_p1)
Пример #7
0
def DrawBasisFunction(N=4, i=0, order=1):
    mesh1D = Mesh1D(N)
    fes = H1(mesh1D, order=order)
    gf = GridFunction(fes)

    gf.vec[:] = 0
    if i >= fes.ndof:
        print(" i is too large. Setting it to", fes.ndof - 1)
        i = fes.ndof - 1

    gf.vec[i] = 1
    Draw1D(mesh1D, [(gf, "Basisfunktion " + str(i))], n_p=2 * order**2)
Пример #8
0
def IndicatorCF(mesh, ba, facets=False):
    """
Returns a CoefficientFunction that evaluates a BitArray. On elements/facets with an index i where
the BitArray evaluates to true the CoefficientFunction will evaluate as 1, otherwise as 0. Similar
functionality (only on elements) can be obtained with BitArrayCF.
    """
    if facets:
        ret = GridFunction(FESpace("facet", mesh, order=0))
        for i in range(len(ba)):
            if ba[i]:
                ret.vec[i] = 1.0
            else:
                ret.vec[i] = 0.0
        return ret
    else:
        return BitArrayCF(BitArray(ba))
Пример #9
0
def update_gridfunction_from_files(
        gfu: GridFunction, file_dict: Dict[Optional[int], str]) -> None:
    """
    Function to take an existing gridfunction and load data into it from one or more files.

    NOTE: It is assumed that the save data in the files is from the same FES and mesh as the existing grid function.
          There is no way to check this in code.

    NOTE: If the FES and mesh are not the same, NGSolve will not necesarily crash,
          it will instead silently return garbage.

    Args:
        file_dict: Dict containing the paths to the files
        gfu: The gridfunction to load the values into
    """

    for key, val in file_dict.items():
        # Check that the file exists.
        if not os.path.isfile(val):
            raise FileNotFoundError('The given file does not exist.')

        if key is None:  # A single gridfunction
            # Confirm that file_dict only has one value, otherwise the gfu values will be overwritten multiple times
            assert len(file_dict) == 1

            gfu.Load(val)
        else:
            # The values for the various components of the gridfunction were saved separately.
            gfu.components[key].Load(val)
Пример #10
0
def CutRatioGF(cutinfo):
    """
Ratio between negative and full part of an element. Vector taken from CutInfo and put into a
piecewise constant GridFunction.
    """
    ret = GridFunction(L2(cutinfo.Mesh(), order=0))
    ret.vec.data = cutinfo.GetCutRatios(VOL)
    return ret
Пример #11
0
def dxtref(mesh, order=None, time_order=-1, **kwargs):
    """
    Differential symbol for the integration over all elements extruded by
    the reference interval [0,1] to space-time prisms.

    Parameters
    ----------
    mesh : ngsolve.Mesh
        The spatial mesh.
        The domain type of interest.
    order : int
        Modify the order of the integration rule used.
    definedon : Region
        Domain description on where the integrator is defined.
    element_boundary : bool
        Integration on each element boundary. Default: False
    element_vb : {VOL, BND, BBND}
        Integration on each element or its (B)boundary. Default: VOL
        (is overwritten by element_boundary if element_boundary 
        is True)
    skeleton : bool
        Integration over element-interface. Default: False.
    deformation : ngsolve.GridFunction
        Mesh deformation. Default: None.
    definedonelements : ngsolve.BitArray
        Allows integration only on elements or facets (if skeleton=True)
        that are marked True. Default: None.
    time_order : int
        Order in time that is used in the space-time integration.
        Default: time_order=-1 means that no space-time rule will be
        applied. This is only relevant for space-time discretizations.

    Return
    ------
        CutDifferentialSymbol(VOL)
    """
    gflset = GridFunction(H1(mesh))
    gflset.vec[:] = 1

    lsetdom = {"levelset": gflset, "domain_type": POS}
    if order is not None:
        lsetdom["order"] = order
    if time_order > -1:
        lsetdom["time_order"] = time_order

    return _dCut_raw(lsetdom, **kwargs)
Пример #12
0
def dmesh(mesh=None, *args, **kwargs):
    """
    Differential symbol for the integration over all elements in the mesh.

    Parameters
    ----------
    mesh : ngsolve.Mesh
        The spatial mesh.
        The domain type of interest.
    definedon : Region
        Domain description on where the integrator is defined.
    element_boundary : bool
        Integration on each element boundary. Default: False
    element_vb : {VOL, BND, BBND}
        Integration on each element or its (B)boundary. Default: VOL
        (is overwritten by element_boundary if element_boundary 
        is True)
    skeleton : bool
        Integration over element-interface. Default: False.
    deformation : ngsolve.GridFunction
        Mesh deformation. Default: None.
    definedonelements : ngsolve.BitArray
        Allows integration only on elements or facets (if skeleton=True)
        that are marked True. Default: None.
    tref : float
        turns a spatial integral resulting in spatial integration rules
        into a space-time quadrature rule with fixed reference time tref

    Return
    ------
        CutDifferentialSymbol(VOL)
    """
    if "tref" in kwargs:
        if mesh == None:
            raise Exception("dx(..,tref..) needs mesh")
        gflset = GridFunction(H1(mesh))
        gflset.vec[:] = 1
        lsetdom = {
            "levelset": gflset,
            "domain_type": POS,
            "tref": kwargs["tref"]
        }
        del kwargs["tref"]
        return _dCut_raw(lsetdom, **kwargs)
    else:
        return dx(*args, **kwargs)
Пример #13
0
def _sol_to_vtu(gfu: GridFunction, sol_path_str: str, output_dir_path: str,
                save_names: str, delete_sol_file: bool, subdivision: int,
                mesh: Mesh) -> str:
    """
    Function that gets parallelized and does the actual sol-to-vtu conversion.

    Args:
        gfu: The grid function into which to load the .sol file
        sol_path_str: The path to the solve file to load
        output_dir_path: The path to the directory to save the .vtu into
        save_names: The names of the variables to save
        delete_sol_file: Whether or not to detele the sol file after
        subdivision: Number of subdivisions on each mesh element
        mesh: The mesh on which the gfu was solved.

    Returns:
        ~: A string containing the entry for the .pvd file for this .vtu file.
    """

    # Get the timestep for this .sol file from its name
    sol_name = sol_path_str.split('/')[-1][:-4]
    time_str = sol_name.split('_')[-1]

    # Name for the .vtu
    filename = output_dir_path + 'vtu/' + sol_name

    # Load data into gfu
    gfu.Load(sol_path_str)

    # Convert gfu components into form needed for VTKOutput
    if len(gfu.components) > 0:
        coefs = [component for component in gfu.components]
    else:
        coefs = [gfu]

    # Write to .vtk
    VTKOutput(ma=mesh,
              coefs=coefs,
              names=save_names,
              filename=filename,
              subdivision=subdivision).Do()

    # Convert .vtk to .vtu
    meshio.read(filename + '.vtk').write(filename + '.vtu')

    # Remove the .vtk
    remove(filename + '.vtk')

    # Delete .sol
    if delete_sol_file:
        remove(sol_path_str)

    # Write timestep in .pvd
    return '<DataSet timestep=\"%e\" group=\"\" part=\"0\" file=\"%s\"/>\n'\
           % (float(time_str), 'vtu/' + filename.split('/')[-1] + '.vtu')
Пример #14
0
def ComputeMatrixEntry2(N=8, order=1, k=1, i=0, j=0):
    mesh1D = Mesh1D(N)
    fes = H1(mesh1D, order=order)  #, dirichlet=)

    gf1 = GridFunction(fes)
    gf2 = GridFunction(fes)

    gf1.vec[:] = 0
    gf1.vec[i] = 1.
    gf2.vec[:] = 0
    gf2.vec[j] = 1.

    Draw1D(mesh1D, [(gf1, "phi_i"), (gf2, "phi_j")],
           n_p=5 * order**2,
           figsize=(12, 3.5))
    Draw1D(mesh1D, [(grad(gf1)[0], "dphi_idx"), (grad(gf2)[0], "dphi_jdx")],
           n_p=5 * order**2,
           figsize=(12, 3.5))
    print("A[i,j] = ",
          Integrate(gf1.Deriv() * gf2.Deriv(), mesh1D, order=2 * (order - 1)))
Пример #15
0
def solvewave(mesh, p, F, q_zero, mu_zero, cwave, exactu=None):

    a, f, X, sep = makeforms(mesh, p, F, q_zero, mu_zero, cwave)
    euz = GridFunction(X)
    c = Preconditioner(type="local", bf=a)
    a.Assemble()
    f.Assemble()

    BVP(bf=a, lf=f, gf=euz, pre=c, maxsteps=10000, prec=1.e-10).Do()
    er = compute_error(euz, sep, exactu)

    return (er, euz, sep, X)
Пример #16
0
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)
Пример #17
0
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)
Пример #18
0
def _facet_jumps(sol: GridFunction, mesh: Mesh) -> float:
    """
    Function to check how continuous the solution is across mesh facets. This
    is mainly of interest when DG is used. Continuous Galerkin FEM solutions
    will always be perfectly continuous across facets.

    Args:
        sol: The solution GridFunction.
        mesh: The mesh that was solved on.

    Returns:
        mag_jumps: The L2 norm of the facet jumps.
    """

    mag_jumps = ngs.sqrt(
        ngs.Integrate((sol - sol.Other())**2 * ngs.dx(element_boundary=True),
                      mesh))

    return mag_jumps
Пример #19
0
def load_coefficientfunction_into_gridfunction(
        gfu: ngs.GridFunction,
        coef_dict: Dict[Optional[int], ngs.CoefficientFunction]) -> None:
    """
    Function to load a coefficientfunction(s) into a gridfunction. Coefficientfunction may have a different dimension
    than the gridfunction and need to be loaded into a specific component.

    Args:
        coef_dict: Dict containing the coefficientfunction(s) and which component they belong to (keys)
        gfu: The gridfunction to load the values into

    """

    for key, val in coef_dict.items():
        if key is None:
            # Confirm that coef_dict only has one value, otherwise the gfu values will be overwritten multiple times
            assert len(coef_dict) == 1
            gfu.Set(val)
        else:
            gfu.components[key].Set(val)
Пример #20
0
    def apply_dirichlet_bcs_to(self, gfu: ngs.GridFunction) -> None:
        """
        Function to set the Dirichlet boundary conditions within the solution GridFunction.

        Args:
            gfu: The GridFunction to add the Dirichlet boundary condition values to
        """
        # NOTE: DO NOT change from definedon=self.mesh.Boundaries(marker) to definedon=marker.
        if len(self.g_D) > 0:
            if len(gfu.components) == 0:  # Single trial functions
                # TODO: IDE is complaining that we don't specify parameter VOL_OR_BND for .Set()
                gfu.Set(self.g_D['u'],
                        definedon=self.mesh.Boundaries(
                            self.dirichlet_names['u']))
            else:  # Multiple trial functions.
                for component_name in self.g_D.keys():
                    # Apply Dirichlet or pinned BCs.
                    i = self.model_components[component_name]
                    gfu.components[i].Set(
                        self.g_D[component_name],
                        definedon=self.mesh.Boundaries(
                            self.dirichlet_names[component_name]))
Пример #21
0
def solvewavedirect(mesh,
                    p,
                    F,
                    q_zero,
                    mu_zero,
                    cwave,
                    exactu=None,
                    epsil=1.e-9):

    a, f, X, sep = makeforms(mesh, p, F, q_zero, mu_zero, cwave, epsil=epsil)

    euz = GridFunction(X)
    a.Assemble()
    f.Assemble()

    f.vec.data += a.harmonic_extension_trans * f.vec
    euz.vec.data = a.mat.Inverse(X.FreeDofs(True)) * f.vec
    euz.vec.data += a.harmonic_extension * euz.vec
    euz.vec.data += a.inner_solve * f.vec

    er = compute_error(euz, sep, exactu)

    return (er, euz, sep, X)
Пример #22
0
p = 3          # polynomial degree
h0 = 1         # coarse mesh size for unit square domain
markprm = 0.5  # percentage of max total error for marking

# SET UP:

mesh = Mesh(unit_square.GenerateMesh(maxh=h0))
q_zero = 'bottom'              # Mesh boundary parts where q and
mu_zero = 'bottom|right|left'  # mu has essential b.c
u00 = exp(-1000 * ((x - 0.5) * (x - 0.5)))  # Nonzero initial condition
cwave = 1.                                  # wave speed
F = ngs.CoefficientFunction((0, 0))         # Zero source

a, f, X, sep = makeforms(mesh, p, F, q_zero, mu_zero, cwave, epsil=1.e-10)

euz = GridFunction(X)           # Contains solution at each adaptive step
q = euz.components[sep[0]]      # Volume (L2) components
mu = euz.components[sep[0]+1]
zq = euz.components[sep[1]]     # Interface components
zmu = euz.components[sep[1]+1]

zq.Set(u00, definedon='bottom')
zmu.Set(-u00, definedon='bottom')

ngs.Draw(mu, autoscale=False,   # draw only one of the solution components
         min=-1.0, max=1.0)


# ADAPTIVE LOOP:

globalerr = 1      # estimated total error
Пример #23
0
# H1-conforming finite element space
fes = H1(mesh, order=3, dirichlet=[1,2,3,4])

# define trial- and test-functions
u = fes.TrialFunction()
v = fes.TestFunction()

# the right hand side
f = LinearForm(fes)
f += 32 * (y*(1-y)+x*(1-x)) * v * dx

# the bilinear-form 
a = BilinearForm(fes, symmetric=True)
a += grad(u)*grad(v)*dx

a.Assemble()
f.Assemble()

# the solution field 
gfu = GridFunction(fes)
gfu.vec.data = a.mat.Inverse(fes.FreeDofs(), inverse="sparsecholesky") * f.vec
# print (u.vec)


# plot the solution (netgen-gui only)
Draw (gfu)
Draw (-grad(gfu), mesh, "Flux")

exact = 16*x*(1-x)*y*(1-y)
print ("L2-error:", sqrt (Integrate ( (gfu-exact)*(gfu-exact), mesh)))
Пример #24
0
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)