Esempio n. 1
0
    def compute(self, get):
        u1 = get(self.valuename1)
        u2 = get(self.valuename2)

        if u1 is None or u2 is None:
            return

        if not (isinstance(u1, GenericFunction)
                or isinstance(u2, GenericFunction)):
            return npdot(u1, u2)

        if not isinstance(u1, GenericFunction):
            u1 = Constant(u1)
            u1, u2 = u2, u1
        if not isinstance(u2, GenericFunction):
            u2 = Constant(u2)

        if isinstance(u2, Function):
            u1, u2 = u2, u1

        assert isinstance(u1, Function)
        assert isinstance(u2, GenericFunction)

        if u1.value_rank() == u2.value_rank():
            if u1.value_rank() == 0:
                V = u1.function_space()
            else:
                V = u1.function_space().sub(0).collapse()
        elif u1.value_rank() > u2.value_rank():
            assert u2.value_rank() == 0
            V = u1.function_space()
            u1, u2 = u2, u1
        else:
            assert isinstance(u2, Function)
            assert u1.value_rank() == 0
            V = u2.function_space()

        #N = max([u1.value_rank(), u2.value_rank()])

        if not hasattr(self, "u"):
            self.u = Function(V)

        if isinstance(u2, Function) and u1.function_space().dim(
        ) == u2.function_space().dim() and u1.value_rank() == 0:
            self.u.vector()[:] = u1.vector().array() * u2.vector().array()
        elif u1.value_rank() == u2.value_rank():
            project(dot(u1, u2), function=self.u, V=self.u.function_space())
        else:
            assert u1.value_rank() == 0
            if isinstance(u1, Constant):
                self.u.vector()[:] = float(u1) * u2.vector().array()
            else:
                project(u1 * u2, function=self.u, V=self.u.function_space())

        return self.u
Esempio n. 2
0
    def output_term(self,
                    term='LHS',
                    norm='none',
                    units='rescaled',
                    output_label=False):

        # cast params as constant functions so that, if they are set to 0, FEniCS still understand
        # what is being integrated
        mu, M = Constant(self.physics.mu), Constant(self.physics.M)
        lam = Constant(self.physics.lam)
        mn, mf = Constant(self.mn), Constant(self.mf)

        D = self.physics.D

        if units == 'rescaled':
            resc = 1.
            str_phi = '\\hat{\\phi}'
            str_nabla2 = '\\hat{\\nabla}^2'
            str_m2 = '\\left( \\frac{\\mu}{m_n} \\right)^2'
            str_lambdaphi3 = '\\lambda\\left(\\frac{m_f}{m_n}\\right)^2\\hat{\\phi}^3'
            str_rho = '\\frac{m_n^{D-2}}{m_f}\\frac{\\hat{\\rho}}{M}'

        elif units == 'physical':
            resc = self.mn**2 * self.mf
            str_phi = '\\phi'
            str_nabla2 = '\\nabla^2'
            str_m2 = '\\mu^2'
            str_lambdaphi3 = '\\lambda\\phi^3'
            str_rho = '\\frac{\\rho}{M}'

        else:
            message = "Invalid choice of units: valid choices are 'physical' or 'rescaled'."
            raise ValueError, message

        phi = self.phi

        # define r for use in the computation of the Laplacian
        r = Expression('x[0]', degree=self.fem.func_degree)

        if term == 'LHS':  # I expand manually the Laplacian into (D-1)/r df/dr + d2f/dr2
            Term = Constant(D-1.)/r * phi.dx(0) + phi.dx(0).dx(0) \
                 + (mu/mn)**2*phi - lam*(mf/mn)**2*phi**3
            label = r"$%s%s + %s%s - %s$" % (str_nabla2, str_phi, str_m2,
                                             str_phi, str_lambdaphi3)
        elif term == 'RHS':
            Term = (mn**(D - 2.) / (mf * M)) * self.source.rho
            label = r"$%s$" % (str_rho)
        elif term == 1:
            Term = Constant(D - 1.) / r * phi.dx(0) + phi.dx(0).dx(0)
            label = r"$%s%s$" % (str_nabla2, str_phi)
        elif term == 2:
            Term = +(mu / mn)**2 * phi
            label = r"$%s%s$" % (str_m2, str_phi)
        elif term == 3:
            Term = -lam * (mf / mn)**2 * phi**3
            label = r"$-%s$" % (str_lambdaphi3)
        elif term == 4:
            Term = (mn**(D - 2.) / (mf * M)) * self.source.rho
            label = r"$%s$" % (str_rho)
        # rescale if needed to get physical units
        Term *= resc

        Term = project(Term, self.fem.dS, self.physics.D, self.fem.func_degree)

        # 'none' = return function, not norm
        if norm == 'none':
            result = Term
            # from here on return a norm. This nested if is to preserve the structure of the original
            # built-in FEniCS norm function
        elif norm == 'linf':
            # infinity norm, i.e. max abs value at vertices
            result = rD_norm(Term.vector(),
                             self.physics.D,
                             self.fem.func_degree,
                             norm_type=norm)
        else:
            result = rD_norm(Term,
                             self.physics.D,
                             self.fem.func_degree,
                             norm_type=norm)

        if output_label:
            return result, label
        else:
            return result
Esempio n. 3
0
def test_estimator_refinement():
    # define source term
    f = Constant("1.0")
    #    f = Expression("10.*exp(-(pow(x[0] - 0.6, 2) + pow(x[1] - 0.4, 2)) / 0.02)", degree=3)

    # set default vector for new indices
    mesh0 = refine(Mesh(lshape_xml))
    fs0 = FunctionSpace(mesh0, "CG", 1)
    B = FEniCSBasis(fs0)
    u0 = Function(fs0)
    diffcoeff = Constant("1.0")
    pde = FEMPoisson()
    fem_A = pde.assemble_lhs(diffcoeff, B)
    fem_b = pde.assemble_rhs(f, B)
    solve(fem_A, u0.vector(), fem_b)
    vec0 = FEniCSVector(u0)

    # setup solution multi vector
    mis = [Multiindex([0]),
           Multiindex([1]),
           Multiindex([0, 1]),
           Multiindex([0, 2])]
    N = len(mis)

    #    meshes = [UnitSquare(i + 3, 3 + N - i) for i in range(N)]
    meshes = [refine(Mesh(lshape_xml)) for _ in range(N)]
    fss = [FunctionSpace(mesh, "CG", 1) for mesh in meshes]

    # solve Poisson problem
    w = MultiVectorWithProjection()
    for i, mi in enumerate(mis):
        B = FEniCSBasis(fss[i])
        u = Function(fss[i])
        pde = FEMPoisson()
        fem_A = pde.assemble_lhs(diffcoeff, B)
        fem_b = pde.assemble_rhs(f, B)
        solve(fem_A, u.vector(), fem_b)
        w[mi] = FEniCSVector(u)
        #        plot(w[mi]._fefunc)

    # define coefficient field
    a0 = Expression("1.0", element=FiniteElement('Lagrange', ufl.triangle, 1))
    #    a = [Expression('2.+sin(2.*pi*I*x[0]+x[1]) + 10.*exp(-pow(I*(x[0] - 0.6)*(x[1] - 0.3), 2) / 0.02)', I=i, degree=3,
    a = (Expression('A*cos(pi*I*x[0])*cos(pi*I*x[1])', A=1 / i ** 2, I=i, degree=2,
        element=FiniteElement('Lagrange', ufl.triangle, 1)) for i in count())
    rvs = (NormalRV(mu=0.5) for _ in count())
    coeff_field = ParametricCoefficientField(a, rvs, a0=a0)

    # refinement loop
    # ===============
    refinements = 3

    for refinement in range(refinements):
        print "*****************************"
        print "REFINEMENT LOOP iteration ", refinement + 1
        print "*****************************"

        # evaluate residual and projection error estimates
        # ================================================
        maxh = 1 / 10
        resind, reserr = ResidualEstimator.evaluateResidualEstimator(w, coeff_field, f)
        projind, projerr = ResidualEstimator.evaluateProjectionError(w, coeff_field, maxh)

        # testing -->
        projglobal, _ = ResidualEstimator.evaluateProjectionError(w, coeff_field, maxh, local=False)
        for mu, val in projglobal.iteritems():
            print "GLOBAL Projection Error for", mu, "=", val
            # <-- testing

        # ==============
        # MARK algorithm
        # ==============

        # setup marking sets
        mesh_markers = defaultdict(set)

        # residual marking
        # ================
        theta_eta = 0.8
        global_res = sum([res[1] for res in reserr.items()])
        allresind = list()
        for mu, resmu in resind.iteritems():
            allresind = allresind + [(resmu.coeffs[i], i, mu) for i in range(len(resmu.coeffs))]
        allresind = sorted(allresind, key=itemgetter(1))
        # TODO: check that indexing and cell ids are consistent (it would be safer to always work with cell indices) 
        marked_res = 0
        for res in allresind:
            if marked_res >= theta_eta * global_res:
                break
            mesh_markers[res[2]].add(res[1])
            marked_res += res[0]

        print "RES MARKED elements:\n", [(mu, len(cell_ids)) for mu, cell_ids in mesh_markers.iteritems()]

        # projection marking
        # ==================
        theta_zeta = 0.8
        min_zeta = 1e-10
        max_zeta = max([max(projind[mu].coeffs) for mu in projind.active_indices()])
        print "max_zeta =", max_zeta
        if max_zeta >= min_zeta:
            for mu, vec in projind.iteritems():
                indmu = [i for i, p in enumerate(vec.coeffs) if p >= theta_zeta * max_zeta]
                mesh_markers[mu] = mesh_markers[mu].union(set(indmu))
                print "PROJ MARKING", len(indmu), "elements in", mu

            print "FINAL MARKED elements:\n", [(mu, len(cell_ids)) for mu, cell_ids in mesh_markers.iteritems()]
        else:
            print "NO PROJECTION MARKING due to very small projection error!"

        # new multiindex activation
        # =========================
        # determine possible new indices
        theta_delta = 0.9
        maxm = 10
        a0_f = coeff_field.mean_func
        Ldelta = {}
        Delta = w.active_indices()
        deltaN = int(ceil(0.1 * len(Delta)))               # max number new multiindices
        for mu in Delta:
            norm_w = norm(w[mu].coeffs, 'L2')
            for m in count():
                mu1 = mu.inc(m)
                if mu1 not in Delta:
                    if m > maxm or m >= coeff_field.length:  # or len(Ldelta) >= deltaN
                        break
                    am_f, am_rv = coeff_field[m]
                    beta = am_rv.orth_polys.get_beta(1)
                    # determine ||a_m/\overline{a}||_{L\infty(D)} (approximately)
                    f = Function(w[mu]._fefunc.function_space())
                    f.interpolate(a0_f)
                    min_a0 = min(f.vector().array())
                    f.interpolate(am_f)
                    max_am = max(f.vector().array())
                    ainfty = max_am / min_a0
                    assert isinstance(ainfty, float)

                    #                    print "A***", beta[1], ainfty, norm_w
                    #                    print "B***", beta[1] * ainfty * norm_w
                    #                    print "C***", theta_delta, max_zeta
                    #                    print "D***", theta_delta * max_zeta
                    #                    print "E***", bool(beta[1] * ainfty * norm_w >= theta_delta * max_zeta)

                    if beta[1] * ainfty * norm_w >= theta_delta * max_zeta:
                        val1 = beta[1] * ainfty * norm_w
                        if mu1 not in Ldelta.keys() or (mu1 in Ldelta.keys() and Ldelta[mu1] < val1):
                            Ldelta[mu1] = val1

        print "POSSIBLE NEW MULTIINDICES ", sorted(Ldelta.iteritems(), key=itemgetter(1), reverse=True)
        Ldelta = sorted(Ldelta.iteritems(), key=itemgetter(1), reverse=True)[:min(len(Ldelta), deltaN)]
        # add new multiindices to solution vector
        for mu, _ in Ldelta:
            w[mu] = vec0
        print "SELECTED NEW MULTIINDICES ", Ldelta

        # create new refined (and enlarged) multi vector
        # ==============================================
        for mu, cell_ids in mesh_markers.iteritems():
            vec = w[mu].refine(cell_ids, with_prolongation=False)
            fs = vec._fefunc.function_space()
            B = FEniCSBasis(fs)
            u = Function(fs)
            pde = FEMPoisson()
            fem_A = pde.assemble_lhs(diffcoeff, B)
            fem_b = pde.assemble_rhs(f, B)
            solve(fem_A, vec.coeffs, fem_b)
            w[mu] = vec