def assemble_lumpedmm(self): """ Assembly lumped mass matrix - equal to 0 on robin boundary since there is no time derivative there. """ print("Assembling lumped mass matrix") mass_form = self.w * self.u * dx mass_action_form = action(mass_form, Constant(1)) self.MM_terms = assemble(mass_action_form) for n in self.robint_nodes_list: self.MM_terms[n] = 1.0 for n in self.robin_nodes_list: self.MM_terms[n] = 0.0 self.mass_matrix = assemble(mass_form) self.mass_matrix.zero() self.mass_matrix.set_diagonal(self.MM_terms) self.scipy_mass_matrix = toscipy(self.mass_matrix)
def test_multi_ps_matrix_node_vector_fs(mesh): """Tests point source applied to a matrix with given constructor PointSource(V, source) and a vector function space when points placed at 3 vertices for 1D, 2D and 3D. Global points given to constructor from rank 0 processor. """ point = [0.0, 0.5, 1.0] rank = MPI.rank(mesh.mpi_comm()) V = VectorFunctionSpace(mesh, "CG", 1, dim=2) u, v = TrialFunction(V), TestFunction(V) w = Function(V) A = assemble(Constant(0.0) * dot(u, v) * dx) dim = mesh.geometry().dim() source = [] point_coords = np.zeros(dim) for p in point: for i in range(dim): point_coords[i - 1] = p if rank == 0: source.append((Point(point_coords), 10.0)) ps = PointSource(V, source) ps.apply(A) # Checks array sums to correct value A.get_diagonal(w.vector()) a_sum = MPI.sum(mesh.mpi_comm(), np.sum(A.array())) assert round(a_sum - 2 * len(point) * 10) == 0 # Check if coordinates are in portion of mesh and if so check that # diagonal components sum to the correct value. mesh_coords = V.tabulate_dof_coordinates() for p in point: for i in range(dim): point_coords[i] = p j = 0 for i in range(len(mesh_coords) // (dim)): mesh_coords_check = mesh_coords[j:j + dim - 1] if np.array_equal(point_coords, mesh_coords_check) is True: assert np.round(w.vector()[j // (dim)] - 10.0) == 0.0 j += dim
def test_stationary_solve(show=False): problem = problems.Crucible() boundaries = problem.wp_boundaries average_temp = 1551.0 material = problem.subdomain_materials[problem.wpi] rho = material.density(average_temp) cp = material.specific_heat_capacity kappa = material.thermal_conductivity my_ds = Measure("ds")(subdomain_data=boundaries) convection = None heat = maelstrom.heat.Heat( problem.Q, kappa, rho, cp, convection, source=Constant(0.0), dirichlet_bcs=problem.theta_bcs_d, neumann_bcs=problem.theta_bcs_n, robin_bcs=problem.theta_bcs_r, my_dx=dx, my_ds=my_ds, ) theta_reference = heat.solve_stationary() theta_reference.rename("theta", "temperature") if show: # with XDMFFile('temperature.xdmf') as f: # f.parameters['flush_output'] = True # f.parameters['rewrite_function_mesh'] = False # f.write(theta_reference) tri = plot(theta_reference) plt.colorbar(tri) plt.show() assert abs(maelstrom.helpers.average(theta_reference) - 1551.0) < 1.0e-1 return theta_reference
def __init__(self, Vm, parameters=[]): """ Vm = FunctionSpace for the parameters m1, and m2 """ self.parameters = {} self.parameters['k'] = 1.0 self.parameters['eps'] = 1e-2 self.parameters['rescaledradiusdual'] = 1.0 self.parameters['print'] = False self.parameters['amg'] = 'default' self.parameters['nb_param'] = 2 self.parameters['use_i'] = False self.parameters.update(parameters) n = self.parameters['nb_param'] use_i = self.parameters['use_i'] assert ((not use_i) * (n > 2)) Vw = FunctionSpace(Vm.mesh(), 'DG', 0) if not use_i: VmVm = createMixedFS(Vm, Vm) VwVw = createMixedFS(Vw, Vw) else: if self.parameters['print']: print '[V_TVPD] Using createMixedFSi' Vms, Vws = [], [] for ii in range(n): Vms.append(Vm) Vws.append(Vw) VmVm = createMixedFSi(Vms) VwVw = createMixedFSi(Vws) self.parameters['Vm'] = VmVm self.parameters['Vw'] = VwVw self.regTV = TVPD(self.parameters) if not use_i: self.m1, self.m2 = Function(Vm), Function(Vm) self.m = Function(VmVm) self.w_loc = Function(VwVw) self.factorw = Function(Vw) self.factorww = Function(VwVw) tmp = interpolate(Constant("1.0"), Vw) self.one = tmp.vector()
def updateCoefficients(self): x, y = SpatialCoordinate(self.mesh) # Init coefficient matrix self.a = as_matrix([[Constant(1.), Constant(0.)], [Constant(0.), Constant(2.)]]) self.b = as_vector([Constant(0.2), Constant(-0.1)]) self.c = Constant(0.1) self.u_ = 0.5 * (self.t**2 + 1) * sin(2 * x * pi) * sin(2 * y * pi) self.u_T = ufl.replace(self.u_, {self.t: self.T[1]}) # Init right-hand side self.f = self.t * sin(2*pi*x) * sin(2*pi*y) \ + inner(self.a, grad(grad(self.u_))) \ + inner(self.b, grad(self.u_)) \ + self.c * self.u_ self.g = Constant(0.0)
def __init__(self): self.T = [0, 3] self.t = Constant(self.T[1]) # self.T = [0, 0.1] # self.alpha = 0.1 self.alpha = 2.38 # self.r = 0.0 self.r = 0.1 self.sigma = 0.59 self.pmin = 0.0 self.pmax = 12.0 self.Imin = 0.0 self.Imax = 2000 self.K0 = 6 self.k1 = 2040.41 self.k2 = 730000 self.k3 = 500 self.k4 = 2500 self.k5 = 1.7 * 365
def scalar_force( self, field ): r""" Returns the magnitude of the scalar force associated to the input field, per unit mass (units :math:`M_p`): .. math :: F_{\varphi} = \frac{\nabla\varphi}{M_P} if :math:`\varphi` is the input field. *Arguments* field the field associated to the scalar force """ grad = self.grad( field, 'physical' ) force = - grad / Constant(self.fields.Mp) force = project( force, self.fem.dS, self.fem.func_degree ) return force
def fluid_setup(v_, p_, n, psi, gamma, dx, mu_f, rho_f, k, dt, theta, **semimp_namespace): F_fluid_linear = rho_f/k*inner(v_["n"] - v_["n-1"], psi)*dx \ + Constant(theta)*inner(sigma_f(p_["n"], v_["n"], mu_f), grad(psi))*dx \ + Constant(1 - theta)*inner(sigma_f(p_["n-1"], v_["n-1"], mu_f), grad(psi))*dx \ + Constant(theta)*inner(div(v_["n"]), gamma)*dx \ + Constant(1 -theta)*inner(div(v_["n-1"]), gamma)*dx F_fluid_nonlinear = Constant(theta)*rho_f*inner(dot(grad(v_["n"]), v_["n"]), psi)*dx \ + Constant(1 - theta)*rho_f*inner(dot(grad(v_["n-1"]), v_["n-1"]), psi)*dx return dict(F_fluid_linear=F_fluid_linear, F_fluid_nonlinear=F_fluid_nonlinear)
def test_compute_point_values(mesh_factory): from numpy import all func, args = mesh_factory mesh = func(*args) e0 = Constant(1) e1 = Constant((1, 2, 3)) e0_values = e0.compute_point_values(mesh) e1_values = e1.compute_point_values(mesh) assert all(e0_values == 1) assert all(e1_values == [1, 2, 3])
def F(u, p, v, q, f, r, mu, my_dx): mu = Constant(mu) # Momentum equation (without the nonlinear Navier term). F0 = (mu * inner(r * grad(u), grad(v)) * 2 * pi * my_dx + mu * u[0] / r * v[0] * 2 * pi * my_dx - dot(f, v) * 2 * pi * r * my_dx) if len(u) == 3: F0 += mu * u[2] / r * v[2] * 2 * pi * my_dx F0 += (p.dx(0) * v[0] + p.dx(1) * v[1]) * 2 * pi * r * my_dx # Incompressibility condition. # div_u = 1/r * div(r*u) F0 += ((r * u[0]).dx(0) + r * u[1].dx(1)) * q * 2 * pi * my_dx # a = mu * inner(r * grad(u), grad(v)) * 2*pi * my_dx \ # - ((r * v[0]).dx(0) + (r * v[1]).dx(1)) * p * 2*pi * my_dx \ # + ((r * u[0]).dx(0) + (r * u[1]).dx(1)) * q * 2*pi * my_dx # # - div(r*v)*p* 2*pi*my_dx \ # # + q*div(r*u)* 2*pi*my_dx return F0
def forms_theta_nlinear(self, v0, Ubar0, dt, theta_map=Constant(1.0), theta_L=Constant(1.0), duh0=Constant((0., 0.)), duh00=Constant((0., 0)), h=Constant((0., 0.)), neumann_idx=99): # Define trial test functions (v, lamb, vbar) = self.__trial_functions() (w, tau, wbar) = self.__test_functions() (zero_vec, h, duh0, duh00) = self.__check_geometric_dimension(h, duh0, duh00) beta_map = self.beta_map n = self.n facet_integral = self.facet_integral # Define v_star v_star = v0 + (1-theta_L) * duh00 + theta_L * duh0 Udiv = v0 + duh0 outer_v_a = outer(w, Udiv) outer_v_a_o = outer(v_star, Udiv) outer_ubar_a = outer(vbar, Ubar0) # Switch to detect in/outflow boundary gamma = conditional(ge(dot(Udiv, n), 0), 0, 1) # LHS contribution s N_a = facet_integral(beta_map*dot(v, w)) G_a = dot(lamb, w)/dt * dx - theta_map*inner(outer_v_a, grad(lamb))*dx \ + theta_map * (1-gamma) * dot(outer_v_a * n, lamb) * self.ds(neumann_idx) L_a = -facet_integral(beta_map * dot(vbar, w)) H_a = facet_integral(dot(outer_ubar_a*n, tau)) \ - dot(outer_ubar_a*n, tau) * self.ds(neumann_idx) B_a = facet_integral(beta_map * dot(vbar, wbar)) # RHS contributions Q_a = dot(Constant(zero_vec), w) * dx R_a = dot(v_star, tau)/dt * dx \ + (1-theta_map)*inner(outer_v_a_o, grad(tau))*dx \ - gamma * dot(h, tau) * self.ds(neumann_idx) S_a = facet_integral(dot(Constant(zero_vec), wbar)) return self.__fem_forms(N_a, G_a, L_a, H_a, B_a, Q_a, R_a, S_a)
def __init__(self, mesh, FuncSpaces_L, FuncSpaces_G, alpha, h_d=[ Expression(('0.0', '0.0'), degree=3), Expression(('0.0', '0.0'), degree=3) ], beta_stab=Constant(0.), ds=ds): self.mixedL = FuncSpaces_L self.mixedG = FuncSpaces_G self.n = FacetNormal(mesh) self.beta_stab = beta_stab self.alpha = alpha self.he = CellDiameter(mesh) self.h_d = h_d self.ds = ds self.gdim = mesh.geometry().dim()
def __init__( self, state, E0, ell, sigma_D0, k_ell=Constant(1.0e-8), user_functional=None, ): self.u = state[0] self.alpha = state[1] self.E0 = E0 self.ell = ell self.sigma_D0 = sigma_D0 self.k_ell = k_ell self.mu_0 = self.mu(0) assert state[0].function_space().ufl_element().value_size() == 1 self.dim = state[0].function_space().ufl_element().value_size() self.user_functional = user_functional
def test_ale(self): print "" print "Testing ALE::move(Mesh& mesh0, const Mesh& mesh1)" # Create some mesh mesh = UnitSquareMesh(4, 5) # Make some cell function # FIXME: Initialization by array indexing is probably # not a good way for parallel test cellfunc = CellFunction('size_t', mesh) cellfunc.array()[0:4] = 0 cellfunc.array()[4:] = 1 # Create submeshes - this does not work in parallel submesh0 = SubMesh(mesh, cellfunc, 0) submesh1 = SubMesh(mesh, cellfunc, 1) # Move submesh0 disp = Constant(("0.1", "-0.1")) submesh0.move(disp) # Move and smooth submesh1 accordignly submesh1.move(submesh0) # Move mesh accordingly parent_vertex_indices_0 = \ submesh0.data().array('parent_vertex_indices', 0) parent_vertex_indices_1 = \ submesh1.data().array('parent_vertex_indices', 0) mesh.coordinates()[parent_vertex_indices_0[:]] = \ submesh0.coordinates()[:] mesh.coordinates()[parent_vertex_indices_1[:]] = \ submesh1.coordinates()[:] # If test passes here then it is probably working # Check for cell quality for sure magic_number = 0.28 rmin = MeshQuality.radius_ratio_min_max(mesh)[0] self.assertTrue(rmin > magic_number)
def test_multi_ps_vector_node_local(mesh): """Tests point source when given constructor PointSource(V, V, point, mag) with a matrix when points placed at 3 node for 1D, 2D and 3D. Local points given to constructor. """ V = FunctionSpace(mesh, "CG", 1) v = TestFunction(V) b = assemble(Constant(0.0) * v * dx) source = [] point_coords = mesh.coordinates()[0] source.append((Point(point_coords), 10.0)) ps = PointSource(V, source) ps.apply(b) # Checks b sums to correct value size = MPI.size(mesh.mpi_comm()) b_sum = b.sum() assert round(b_sum - size * 10.0) == 0
def updateCoefficients(self): # Init coefficient matrix x, y = SpatialCoordinate(self.mesh) self.a = self.gamma[0] * \ as_matrix([[1.0, 0.0], [0.0, 1.0]]) self.b = as_vector([Constant(1.0), Constant(1.0)]) self.c = Constant(0.0) # Init right-hand side self.f = -Constant(1.0) self.u_T = Constant(0.0) # Set boundary conditions self.g = Constant(0.0)
def test_multi_ps_vector_node(mesh): """Tests point source when given constructor PointSource(V, V, point, mag) with a matrix when points placed at 3 node for 1D, 2D and 3D. Global points given to constructor from rank 0 processor. """ point = [0.0, 0.5, 1.0] dim = mesh.geometry().dim() rank = MPI.rank(mesh.mpi_comm()) V = FunctionSpace(mesh, "CG", 1) v = TestFunction(V) b = assemble(Constant(0.0) * v * dx) source = [] point_coords = np.zeros(dim) for p in point: for i in range(dim): point_coords[i - 1] = p if rank == 0: source.append((Point(point_coords), 10.0)) ps = PointSource(V, source) ps.apply(b) # Checks b sums to correct value b_sum = b.sum() assert round(b_sum - len(point) * 10.0) == 0 # Checks values added to correct part of vector mesh_coords = V.tabulate_dof_coordinates() for p in point: for i in range(dim): point_coords[i] = p j = 0 for i in range(len(mesh_coords) // (dim)): mesh_coords_check = mesh_coords[j:j + dim - 1] if np.array_equal(point_coords, mesh_coords_check) is True: assert np.round(b.array()[j // (dim)] - 10.0) == 0.0 j += dim
def __init__( self, state, E0, nu, ell, sigma_D0, k_res=Constant(1.0e-8), user_functional=None, ): self.u = state['u'] self.alpha = state['alpha'] self.E0 = E0 self.nu = nu self.ell = ell self.sigma_D0 = sigma_D0 self.k_res = k_res self.lmbda_0 = self.lmbda3D(0) self.mu_0 = self.mu3D(0) self.dim = self.u.function_space().ufl_element().value_size() self.user_functional = user_functional
def __init__(self, energy, state, bcs=None): """ Initialises the damage problem. Arguments: * energy * state * boundary conditions """ NonlinearProblem.__init__(self) self.type = "snes" self.bcs = bcs self.state = state alpha = state["alpha"] V = alpha.function_space() alpha_v = TestFunction(V) dalpha = TrialFunction(V) self.energy = energy self.F = derivative(energy, alpha, alpha_v) self.J = derivative(self.F, alpha, dalpha) self.lb = alpha.copy(True).vector() self.ub = interpolate(Constant(1.), V).vector()
def adaptive(self, mesh, eigv, eigf): """Refine mesh based on residual errors.""" fraction = 0.1 C = FunctionSpace(mesh, "DG", 0) # constants on triangles w = TestFunction(C) h = CellSize(mesh) n = FacetNormal(mesh) marker = CellFunction("bool", mesh) print len(marker) indicators = np.zeros(len(marker)) for e, u in zip(eigv, eigf): errform = avg(h) * jump(grad(u), n) ** 2 * avg(w) * dS \ + h * (inner(grad(u), n) - Constant(e) * u) ** 2 * w * ds if self.degree > 1: errform += h**2 * div(grad(u))**2 * w * dx indicators[:] += assemble(errform).array() # errors for each cell print "Residual error: ", sqrt(sum(indicators) / len(eigv)) cutoff = sorted(indicators, reverse=True)[int(len(indicators) * fraction) - 1] marker.array()[:] = indicators > cutoff # mark worst errors mesh = refine(mesh, marker) return mesh
def make_smoothing_solver(V, kappa=None): ''' Important --------- * Smoothing is most effective when the sensitivities are defined over the whole domain. In practice, this is rarely the case. * Smoothing works well enough when the sensitivities are defined over a subdomain but that is the same dimension as the mesh. In such a case, the smoothing will be relatively poor on the boundary of the subdomain. * Smoothing does not work well when the sensitivities are defined over a boundary of the domain. More generally, when the sensitivity domain is lower dimension than the mesh. In this case, this type of smoothing is quite useless. Returns ------- smoothing_solver: Returns the solver that solves the smoothing problem that is the linear system `M x_smoothed = x` where `x` is the vector of unsmoothed values. The smoothing solver can be invoked as `smoothing_solver.solve(x, x)`. ''' v0 = dolfin.TestFunction(V) v1 = dolfin.TrialFunction(V) a = dot(v1,v0)*dolfin.dx if kappa is not None and float(kappa) != 0.0: if isinstance(kappa, (float, int)): kappa = Constant(kappa) a += kappa*inner(grad(v1), grad(v0))*dolfin.dx smoothing_solver = dolfin.LUSolver(assemble(a), "mumps") smoothing_solver.parameters["symmetric"] = True return smoothing_solver
def problem_sinsin(): """cosine example. """ def mesh_generator(n): return UnitSquareMesh(n, n, "left/right") x = sympy.DeferredVector("x") # Choose the solution such that the boundary conditions are fulfilled # exactly. Also, multiply with x**2 to make sure that the right-hand side # doesn't contain the term 1/x. Although it looks like a singularity at # x=0, this terms is esentially harmless since the volume element 2*pi*x is # used throughout the code, canceling out with the 1/x. However, Dolfin has # problems with this, cf. # <https://bitbucket.org/fenics-project/dolfin/issues/831/some-problems-with-quadrature-expressions>. solution = { "value": x[0]**2 * sympy.sin(pi * x[0]) * sympy.sin(pi * x[1]), "degree": MAX_DEGREE, } # Produce a matching right-hand side. phi = solution["value"] kappa = 2.0 rho = 3.0 cp = 5.0 conv = [1.0, 2.0] rhs_sympy = sympy.simplify( -1.0 / x[0] * sympy.diff(kappa * x[0] * sympy.diff(phi, x[0]), x[0]) - 1.0 / x[0] * sympy.diff(kappa * x[0] * sympy.diff(phi, x[1]), x[1]) + rho * cp * conv[0] * sympy.diff(phi, x[0]) + rho * cp * conv[1] * sympy.diff(phi, x[1])) rhs = { "value": Expression(helpers.ccode(rhs_sympy), degree=MAX_DEGREE), "degree": MAX_DEGREE, } return mesh_generator, solution, rhs, triangle, kappa, rho, cp, Constant( conv)
def Fluid_tentative_variation(v_, p_, d_, dvp_, w, w_f, v_tilde_n1, \ psi, beta, gamma, dx_f, mu_f, rho_f, k, dt, **semimp_namespace): d_tent = dvp_["tilde"].sub(0, deepcopy=True) d_n = dvp_["tilde"].sub(0, deepcopy=True) d_n1 = dvp_["n-1"].sub(0, deepcopy=True) v_n1 = dvp_["n-1"].sub(1, deepcopy=True) #Reuse of TrialFunction w, TestFunction beta #used in extrapolation assuming same degree F_tentative = rho_f/k*J_(d_tent)*inner(w - v_n1, beta)*dx_f F_tentative += rho_f*inner(J_(d_tent)*grad(w)*inv(F_(d_tent)) \ * (v_tilde_n1 - 1./k*(d_n - d_n1)), beta)*dx_f F_tentative += J_(d_tent)*inner(mu_f*D_U(d_tent, w), D_U(d_tent, beta))*dx_f F_tentative -= inner(Constant((0, 0)), beta)*dx_f return dict(F_tentative=F_tentative)
def compute(self, get): u = get("Velocity") mu = get("DynamicViscosity") if isinstance(mu, (float, int)): mu = Constant(mu) n = self._n T = -mu * dot((grad(u) + grad(u).T), n) Tn = dot(T, n) Tt = T - Tn * n tau_form = dot(self.v, Tt) * ds() assemble(tau_form, tensor=self.tau.vector()) #self.b[self._keys] = self.tau.vector()[self._values] # FIXME: This is not safe!!! get_set_vector(self.b, self._keys, self.tau.vector(), self._values, self._temp_array) # Ensure proper scaling self.solver.solve(self.tau_boundary.vector(), self.b) return self.tau_boundary
def main(solver, N: int, dt: float, T: float, theta: float) -> Tuple[float, float, float, float, float]: # Create cardiac model mesh = UnitSquareMesh(N, N) time = Constant(0.0) cell_model = NoCellModel() ac_str = "cos(t)*cos(2*pi*x[0])*cos(2*pi*x[1]) + 4*pow(pi, 2)*cos(2*pi*x[0])*cos(2*pi*x[1])*sin(t)" stimulus = Expression(ac_str, t=time, degree=5) ps = solver.default_parameters() ps["Chi"] = 1.0 ps["Cm"] = 1.0 _solver = solver(mesh, time, 1.0, 1.0, stimulus, parameters=ps) # Define exact solution (Note: v is returned at end of time # interval(s), u is computed at somewhere in the time interval # depending on theta) v_exact = Expression("cos(2*pi*x[0])*cos(2*pi*x[1])*sin(t)", t=T, degree=5) u_exact = Expression("-cos(2*pi*x[0])*cos(2*pi*x[1])*sin(t)/2.0", t=T - (1 - theta) * dt, degree=5) # Define initial condition(s) vs0 = Function(_solver.V) vs_, *_ = _solver.solution_fields() vs_.assign(vs0) # Solve for _, (vs_, vur) in _solver.solve(0, T, dt): continue # Compute errors v, u, *_ = vur.split(deepcopy=True) v_error = errornorm(v_exact, v, "L2", degree_rise=5) u_error = errornorm(u_exact, u, "L2", degree_rise=5) return v_error, u_error, mesh.hmin(), dt, T
def solve(self): """ Solves the stokes equation with the current multimesh """ (u, p) = TrialFunctions(self.VQ) (v, q) = TestFunctions(self.VQ) n = FacetNormal(self.multimesh) h = 2.0 * Circumradius(self.multimesh) alpha = Constant(6.0) tensor_jump = lambda u: outer(u("+"), n("+")) + outer(u("-"), n("-")) a_s = inner(grad(u), grad(v)) * dX a_IP = - inner(avg(grad(u)), tensor_jump(v))*dI\ - inner(avg(grad(v)), tensor_jump(u))*dI\ + alpha/avg(h) * inner(jump(u), jump(v))*dI a_O = inner(jump(grad(u)), jump(grad(v))) * dO b_s = -div(u) * q * dX - div(v) * p * dX b_IP = jump(u, n) * avg(q) * dI + jump(v, n) * avg(p) * dI l_s = inner(self.f, v) * dX s_C = h*h*inner(-div(grad(u)) + grad(p), -div(grad(v)) - grad(q))*dC\ + h("+")*h("+")*inner(-div(grad(u("+"))) + grad(p("+")), -div(grad(v("+"))) + grad(q("+")))*dO l_C = h*h*inner(self.f, -div(grad(v)) - grad(q))*dC\ + h("+")*h("+")*inner(self.f("+"), -div(grad(v("+"))) - grad(q("+")))*dO a = a_s + a_IP + a_O + b_s + b_IP + s_C l = l_s + l_C A = assemble_multimesh(a) L = assemble_multimesh(l) [bc.apply(A, L) for bc in self.bcs] self.VQ.lock_inactive_dofs(A, L) solve(A, self.w.vector(), L, "mumps") self.splitMMF()
def __getattr__(self, attr): if attr in self._cache: return self._cache[attr] materials = {} for domain, material in self._materials.items(): ids = self._state.domain_ids(domain) for id in ids: if materials.has_key(id): materials[id] = Material(materials[id], material) else: materials[id] = material # scalar or vector parameter V = None expr = None if len(self._materials) == 0: self._cache[attr] = Constant(getattr(self._base_material, attr)) else: for material in [self._base_material] + self._materials.values(): try: value = getattr(material, attr) if isinstance(value, tuple) or isinstance(value, list): assert len(value) == 3 V = VectorFunctionSpace(self._state.mesh, 'DG', 0) expr = VectorCellExpr(attr, self._state.cell_domains, self._base_material, materials) else: V = FunctionSpace(self._state.mesh, 'DG', 0) expr = CellExpr(attr, self._state.cell_domains, self._base_material, materials) break except AttributeError: continue self._cache[attr] = interpolate(expr, V) return self._cache[attr]
def test_multi_ps_matrix_node_local(mesh): """Tests point source when given constructor PointSource(V, V, point, mag) with a matrix when points placed at 3 node for 1D, 2D and 3D. Local points given to constructor. """ V = FunctionSpace(mesh, "CG", 1) u, v = TrialFunction(V), TestFunction(V) w = Function(V) A = assemble(Constant(0.0) * u * v * dx) source = [] point_coords = mesh.coordinates()[0] source.append((Point(point_coords), 10.0)) ps = PointSource(V, source) ps.apply(A) # Checks matrix sums to correct value. A.get_diagonal(w.vector()) size = MPI.size(mesh.mpi_comm()) a_sum = MPI.sum(mesh.mpi_comm(), np.sum(A.array())) assert round(a_sum - size * 10.0) == 0
def test_pointsource_vector(mesh): """Tests point source when given constructor PointSource(V, point, mag) with a vector that isn't placed at a node for 1D, 2D and 3D. Global points given to constructor from rank 0 processor """ cell = Cell(mesh, 0) point = cell.midpoint() rank = MPI.rank(mesh.mpi_comm()) V = FunctionSpace(mesh, "CG", 1) v = TestFunction(V) b = assemble(Constant(0.0) * v * dx) if rank == 0: ps = PointSource(V, point, 10.0) else: ps = PointSource(V, []) ps.apply(b) # Checks array sums to correct value b_sum = b.sum() assert round(b_sum - 10.0) == 0
def __init__(self, domain): rho, mu, dt, g = domain.rho, domain.mu, domain.dt, domain.g u, u_1, p_1, vu = domain.u, domain.u_1, domain.p_1, domain.vu n = FacetNormal(domain.mesh) acceleration = rho * inner((u - u_1) / dt, vu) * dx diffusion = (-inner(mu * (grad(u_1) + grad(u_1).T), grad(vu)) * dx + dot(mu * (grad(u_1) + grad(u_1).T) * n, vu) * ds) body_force = dot(g*rho, vu)*dx \ + dot(Constant((0.0, 0.0)), vu) * ds # diffusion = (mu*inner(grad(u_1), grad(vu))*dx # - mu*dot(nabla_grad(u_1)*n, vu)*ds) # int. by parts pressure = inner(p_1, div(vu)) * dx - dot(p_1 * n, vu) * ds # int. by parts # TODO: what is better? # convection = dot(div(rho*outer(u_1, u_1)), vu) * dx # not stable! convection = rho * dot(dot(u_1, nabla_grad(u_1)), vu) * dx F_impl = -acceleration - convection + diffusion + pressure + body_force self.a, self.L = lhs(F_impl), rhs(F_impl) self.domain = domain self.A = assemble(self.a) [bc.apply(self.A) for bc in domain.bcu] return
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
def test_time_step(): problem = problems.Crucible() boundaries = problem.wp_boundaries # The melting point of GaAs is 1511 K. average_temp = 1520.0 f = Constant(0.0) material = problem.subdomain_materials[problem.wpi] rho = material.density(average_temp) cp = material.specific_heat_capacity kappa = material.thermal_conductivity my_ds = Measure("ds")(subdomain_data=boundaries) # from dolfin import DirichletBC convection = None heat = maelstrom.heat.Heat( problem.Q, kappa, rho, cp, convection, source=Constant(0.0), dirichlet_bcs=problem.theta_bcs_d, neumann_bcs=problem.theta_bcs_n, robin_bcs=problem.theta_bcs_r, my_dx=dx, my_ds=my_ds, ) # create time stepper # stepper = parabolic.ExplicitEuler(heat) stepper = parabolic.ImplicitEuler(heat) # stepper = parabolic.Trapezoidal(heat) theta0 = project(Constant(average_temp), problem.Q) # theta0 = heat.solve_stationary() theta0.rename("theta0", "temperature") theta1 = Function(problem.Q) theta1 = Function(problem.Q) t = 0.0 dt = 1.0e-3 end_time = 10 * dt with XDMFFile("temperature.xdmf") as f: f.parameters["flush_output"] = True f.parameters["rewrite_function_mesh"] = False f.write(theta0, t) while t < end_time: theta1.assign(stepper.step(theta0, t, dt)) theta0.assign(theta1) t += dt # f.write(theta0, t) assert abs(maelstrom.helpers.average(theta0) - 1519.81) < 1.0e-2 return