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
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
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