def test_formulation_2_traps_1_material(): ''' Test function formulation() with 2 intrinsic traps and 1 material ''' # Set parameters dt = 1 traps = [{ "energy": 1, "density": 2, "materials": [1] }, { "energy": 1, "density": 2, "materials": [1] }] materials = [{ "alpha": 1, "beta": 2, "density": 3, "borders": [0, 1], "E_diff": 4, "D_0": 5, "id": 1 }] extrinsic_traps = [] # Prepare mesh = fenics.UnitIntervalMesh(10) V = fenics.VectorFunctionSpace(mesh, 'P', 1, len(traps)+1) u = fenics.Function(V) u_n = fenics.Function(V) v = fenics.TestFunction(V) solutions = list(fenics.split(u)) previous_solutions = list(fenics.split(u_n)) testfunctions = list(fenics.split(v)) mf = fenics.MeshFunction('size_t', mesh, 1, 1) dx = fenics.dx(subdomain_data=mf) temp = fenics.Expression("300", degree=0) flux_ = fenics.Expression("1", degree=0) F, expressions = FESTIM.formulation( traps, extrinsic_traps, solutions, testfunctions, previous_solutions, dt, dx, materials, temp, flux_) # Transient sol expected_form = ((solutions[0] - previous_solutions[0]) / dt) * \ testfunctions[0]*dx # Diffusion sol expected_form += 5 * fenics.exp(-4/8.6e-5/temp) * \ fenics.dot( fenics.grad(solutions[0]), fenics.grad(testfunctions[0]))*dx(1) # Source sol expected_form += -flux_*testfunctions[0]*dx # Transient trap 1 expected_form += ((solutions[1] - previous_solutions[1]) / dt) * \ testfunctions[1]*dx # Trapping trap 1 expected_form += - 5 * fenics.exp(-4/8.6e-5/temp)/1/1/2 * \ solutions[0] * (2 - solutions[1]) * \ testfunctions[1]*dx(1) # Detrapping trap 1 expected_form += 1e13*fenics.exp(-1/8.6e-5/temp)*solutions[1] * \ testfunctions[1]*dx(1) # Source detrapping sol expected_form += ((solutions[1] - previous_solutions[1]) / dt) * \ testfunctions[0]*dx # Transient trap 2 expected_form += ((solutions[2] - previous_solutions[2]) / dt) * \ testfunctions[2]*dx # Trapping trap 2 expected_form += - 5 * fenics.exp(-4/8.6e-5/temp)/1/1/2 * \ solutions[0] * (2 - solutions[2]) * \ testfunctions[2]*dx(1) # Detrapping trap 2 expected_form += 1e13*fenics.exp(-1/8.6e-5/temp)*solutions[2] * \ testfunctions[2]*dx(1) # Source detrapping 2 sol expected_form += ((solutions[2] - previous_solutions[2]) / dt) * \ testfunctions[0]*dx assert expected_form.equals(F) is True
def create_step_functionals(self): u, v = self._sp.u, self._sp.v u0, v0 = self._sp.u0, self._sp.v0 a0 = self._sp.a0 bf = self._sp.bf ut = self._sp.ut F, F0 = self._sp.F, self._sp.F0 density = self._sp.density constitutive_model = self._sp.constitutive_model self.d_LHS = fe.inner(u, ut) * density * fe.dx \ - pow(self._dt, 2) * self._beta * fe.inner(F * constitutive_model.stress(F), fe.grad(ut)) * fe.dx self.d_RHS = density * (fe.inner(u0, ut) * fe.dx + self._dt * fe.inner(v0, ut) * fe.dx + pow(self._dt, 2) * (0.5 - self._beta) * fe.inner(a0, ut) * fe.dx) \ - pow(self._dt, 2) * self._beta * (fe.inner(bf, ut) * fe.dx)
# Define boundary condition u_D = fs.Expression(u_code, degree=2) def boundary(x, on_boundary): return on_boundary bc = fs.DirichletBC(V, u_D, boundary) # Define variational problem u = fs.Function(V) v = fs.TestFunction(V) f = fs.Expression(f_code, degree=2) F = q(u) * fs.dot(fs.grad(u), fs.grad(v)) * fs.dx - f * v * fs.dx a, L = fs.lhs(F), fs.rhs(F) # Create VTK file for saving solution vtkfile = fs.File('solution.pvd') #Compute Solution fs.solve(F == 0, u, bc) #plot solution fs.plot(u) # Compute maximum error at vertices. This computation illustrates # an alternative to using compute_vertex_values as in poisson.py. u_e = fs.interpolate(u_D, V) error_max = np.abs(u_e.vector() - u.vector()).max()
VW = fn.TestFunctions( V) # test function potential concentration lagrange multi v, w, mu = VW[0], VW[1:M + 1], VW[M + 1:] #lets try rot r = fn.Expression('x[0]', degree=0) # changing concentrations charges Rho = 0 for i in range(M): if i % 2: Rho += -c[i] else: Rho += c[i] PoissonLeft = (fn.dot(fn.grad(u), fn.grad(v))) * fn.dx # weak solution Poisson left PoissonRight = -(Rho) * v * fn.dx # weak solution Poisson right NernstPlanck = 0 for i in range(M): if i % 2: NernstPlanck += fn.dot( (-fn.grad(c[i]) + c[i] * fn.grad(u)), fn.grad( w[i])) * fn.dx # weak solution Nernst-Planck else: NernstPlanck += fn.dot( (-fn.grad(c[i]) - c[i] * fn.grad(u)), fn.grad( w[i])) * fn.dx # weak solution Nernst-Planck constraint = 0 for i in range(M):
def eps(u): return fn.sym(fn.grad(u))
def explicit(d_, w_, k): E = grad(d_["n-1"]) + grad(d_["n-1"]).T \ + grad(d_["n-1"]).T*grad(d_["n-1"]) return 0.5 * E
def cn_before_ab_higher_order(d_, w_, k): E = 0.5*(grad(d_["n"]).T + grad(d_["n-1"]).T + grad(d_["n"]) + grad(d_["n-1"])) \ + 0.5*((grad(d_["n-1"] + k*(23./12*w_["n-1"] - 4./3*w_["n-2"] + 5/12.*w_["n-3"])).T \ * grad(d_["n"])) + (grad(d_["n-1"]).T*grad(d_["n-1"]))) return 0.5 * E
def k(u, v): return inner(sigma(u), sym(grad(v))) * dx
"(x[0] >= -0.2) && (x[0] <= 0.2) && near(x[1], 0.75) && on_boundary") GammaU = fn.CompiledSubDomain( "(near(x[0], -0.5) || near(x[0], 0.5) ) && on_boundary") GammaU.mark(bdry, 31) FooT.mark(bdry, 32) ds = fn.Measure("ds", subdomain_data=bdry) bcU = fn.DirichletBC(Hh.sub(0), u_g, bdry, 31) bcP = fn.DirichletBC(Hh.sub(2), p_g, bdry, 32) bcs = [bcU, bcP] # weak form PLeft = 2*mu*fn.inner(strain(u),strain(v)) * fn.dx \ - fn.div(v) * phi * fn.dx \ + (c0/alpha + 1.0/lmbda)* p * q * fn.dx \ + kappa/(alpha*nu) * fn.dot(fn.grad(p),fn.grad(q)) * fn.dx \ - 1.0/lmbda * phi * q * fn.dx \ - fn.div(u) * psi * fn.dx \ + 1.0/lmbda * psi * p * fn.dx \ - 1.0/lmbda * phi * psi * fn.dx PRight = fn.dot(f, v) * fn.dx + fn.dot(h_g, v) * ds(32) Sol = fn.Function(Hh) # solve linear system fn.solve(PLeft == PRight, Sol, bcs) u, phi, p = Sol.split() u.rename("u", "u") fileU << u
# -- Spatial domain ne = 2**7 L = 15 mesh = fe.IntervalMesh(int(ne),0,L) degQ = 1 degA = 1 QE = fe.FiniteElement("Lagrange", cell=mesh.ufl_cell(), degree=degQ) AE = fe.FiniteElement("Lagrange", cell=mesh.ufl_cell(), degree=degA) ME = fe.MixedElement([AE,QE]) V = fe.FunctionSpace(mesh,ME) V_A = V.sub(0) V_Q = V.sub(1) (v1,v2) = fe.TestFunctions(V) dv1 = fe.grad(v1)[0] dv2 = fe.grad(v2)[0] (u1,u2) = fe.TrialFunctions(V) U0 = fe.Function(V) U0.assign( fe.Expression( ( 'A0', 'Q0' ) , A0=A0, Q0=Q0, degree=1 ) ) Un = fe.Function(V) Un.assign( fe.Expression( ( 'A0', 'Q0' ) , A0=A0, Q0=Q0, degree=1 ) ) (u01,u02) = fe.split(U0) (un1,un2) = fe.split(Un) du01 = fe.grad(u01)[0] ; du02 = fe.grad(u02)[0] dun1 = fe.grad(un1)[0] ; dun2 = fe.grad(un2)[0] B0 = getB(u01,u02) H0 = getH(u01,u02) HdUdz0 = matMult(H0,[du01, du02])
A_fenics = fenics.PETScMatrix(A_petsc) return A_fenics if perform_tests: import numpy as np from time import time # Make Laplacian matrix in fenics n = 10 mesh = fenics.UnitCubeMesh(n, n, n) V = fenics.FunctionSpace(mesh, 'CG', 1) u = fenics.TrialFunction(V) v = fenics.TestFunction(V) a = fenics.inner(fenics.grad(u), fenics.grad(v)) * fenics.dx + u * v * fenics.dx f = fenics.Function(V) f.vector()[:] = np.random.randn(V.dim()) b = f * v * fenics.dx b_fenics = fenics.assemble(b) b_numpy = b_fenics[:] A_fenics = fenics.assemble(a) # Test correctness of matrix converters A_scipy = convert_fenics_csr_matrix_to_scipy_csr_matrix(A_fenics) A_fenics2 = convert_scipy_csr_matrix_to_fenics_csr_matrix(A_scipy)
Ct4 = fe.Constant(2) d1 = fe.Expression('x[0] - 0', degree=1) #d2 = fe.Expression('1 - x[0]', degree=1) #d3 = fe.Expression('1 - x[1]', degree=1) d = fe.Expression('x[1] - 0', degree=1) #d = fe.Constant(10) #d = Min(d1, d4) xi = nu_trial / nu fv1 = xi**3 / (xi**3 + Cv1 * Cv1 * Cv1) #fv1 = fe.elem_pow(xi, 3) / (fe.elem_pow(xi, 3) + Cv1 * Cv1 * Cv1) fv2 = 1 - xi / (1 + xi * fv1) ft2 = Ct3 * fe.exp(-Ct4 * xi * xi) Omega = fe.Constant(0.5) * (fe.grad(u) - fe.grad(u).T) S = fe.sqrt(EPSILON + fe.Constant(2) * fe.inner(Omega, Omega)) Stilde = S + nu_trial / (kappa * kappa * d * d) * fv2 ft2 = Ct3 * fe.exp(fe.Constant(-1) * Ct4 * xi * xi) r = Min(nu_trial / (Stilde * kappa * kappa * d * d), 10) g = r + Cw2 * (r * r * r * r * r * r - r) fw = fe.elem_pow( EPSILON + abs(g * ((1 + Cw3 * Cw3 * Cw3 * Cw3 * Cw3 * Cw3) / (g * g * g * g * g * g + Cw3 * Cw3 * Cw3 * Cw3 * Cw3 * Cw3))), fe.Constant(1. / 6.)) ns_conv = fe.inner(v, fe.grad(u) * u) * fe.dx ns_press = p * fe.div(v) * fe.dx s = fe.grad(u) + fe.grad(u).T if MODEL:
UC = fn.Function(V) uc = fn.split(UC) # trial function potential concentration lagrange multi u, c, lam = uc[0], uc[1:M+1], uc[M+1:] VW = fn.TestFunctions(V) # test function potential concentration lagrange multi v, w, mu = VW[0], VW[1:M+1], VW[M+1:] # changing concentrations charges Rho = 0 for i in range(M): if i%2: Rho += -c[i] else: Rho += c[i] PoissonLeft = (fn.dot(alpha*fn.grad(u), fn.grad(v)))*fn.dx # weak solution Poisson left PoissonRight = -(Rho)*beta*v*fn.dx # weak solution Poisson right NernstPlanck = 0 for i in range(M): if i%2: NernstPlanck += fn.dot(-gamma*fn.grad(c[i]) + c[i]*delta*fn.grad(u),fn.grad(w[i]))*fn.dx # weak solution Nernst-Planck else: NernstPlanck += fn.dot(-gamma*fn.grad(c[i]) - c[i]*delta*fn.grad(u),fn.grad(w[i]))*fn.dx # weak solution Nernst-Planck constraint = 0 for i in range(M): constraint += lam[i] * w[i] * fn.dx + (c[i] - c_avg) * mu[i] * fn.dx #constraint a la hoermann PNP_xy = PoissonLeft + PoissonRight + NernstPlanck + constraint # PNP system
def half_exp_dyn(w0, dt=1.e-5, t_end=1.e-4, show_plots=False): u0 = w0.u p0 = w0.p v0 = w0.v bcs_u, bcs_p, bcs_v = load_2d_muscle_bc(V_u, V_pv.sub(0), V_pv.sub(1), boundaries) F = deformation_grad(u0) I_1, I_2, J = invariants(F) F_iso = isochronic_deformation_grad(F, J) #I_1_iso, I_2_iso = invariants(F_iso)[0:2] W = material_mooney_rivlin(I_1, I_2, c_10, c_01) g = incompr_constr(J) # Lagrange function (without constraint) L = -W P = first_piola_stress(L, F) G = incompr_stress(g, F) # a_dyn_u = inner(u1 - u0, eta) * dx - dt * inner(v1, eta) * dx u1 = fe.TrialFunction(V_u) eta = fe.TestFunction(V_u) #u11 = fe.Function(V_u) #F1 = deformation_grad(u11) #g1 = incompr_constr(fe.det(F1)) #G1 = incompr_stress(g1, F1) (p1, v1) = fe.TrialFunctions(V_pv) (q, xi) = fe.TestFunctions(V_pv) a_dyn_u = inner(u1 - u0, eta) * dx - dt * inner(v0, eta) * dx a_dyn_p = fe.tr(G * grad(v1)) * q * dx #a_dyn_v = rho*inner(v1-v0, xi)*dx + dt*(inner(P + p0*G, grad(xi))*dx - inner(B, xi)*dx) a_dyn_v = rho * inner(v1 - v0, xi) * dx + dt * (inner( P, grad(xi)) * dx + inner(p1 * G, grad(xi)) * dx - inner(B, xi) * dx) a_u = fe.lhs(a_dyn_u) l_u = fe.rhs(a_dyn_u) a_pv = fe.lhs(a_dyn_p + a_dyn_v) l_pv = fe.rhs(a_dyn_p + a_dyn_v) u1 = fe.Function(V_u) pv1 = fe.Function(V_pv) sol = [] vol = fe.assemble(1. * dx) A_u = fe.assemble(a_u) A_pv = fe.assemble(a_pv) for bc in bcs_u: bc.apply(A_u) t = 0 while t < t_end: print("progress: %f" % (100. * t / t_end)) # update displacement u L_u = fe.assemble(l_u) fe.solve(A_u, u1.vector(), L_u) u0.assign(u1) L_pv = fe.assemble(l_pv) for bc in bcs_p + bcs_v: bc.apply(A_pv, L_pv) fe.solve(A_pv, pv1.vector(), L_pv) if fe.norm(pv1.vector()) > 1e8: print('ERROR: norm explosion') break # update initial values for next step w0.u = u1 w0.pv = pv1 p0.assign(w0.p) v0.assign(w0.v) t += dt if show_plots: # plot result fe.plot(w0.sub(0), mode='displacement') plt.show() # save solutions sol.append(Solution(t=t)) sol[-1].upv.assign(w0) return sol, W
def main(): """Main function. Organizes workflow.""" fname = str(INPUTS['filename']) term = Terminal() print( term.yellow + "Working on file {}.".format(fname) + term.normal ) # Load mesh and physical domains from file. mesh = fe.Mesh(fname + ".xml") if INPUTS['saving']['mesh']: fe.File(fname + "_mesh.pvd") << mesh if INPUTS['plotting']['mesh']: fe.plot(mesh, title='Mesh') subdomains = fe.MeshFunction( 'size_t', mesh, fname + '_physical_region.xml') if INPUTS['saving']['subdomains']: fe.File(fname + "_subdomains.pvd") << subdomains if INPUTS['plotting']['subdomains']: fe.plot(subdomains, title='Subdomains') # function space for temperature/concentration func_space = fe.FunctionSpace( mesh, INPUTS['element_type'], INPUTS['element_degree'], constrained_domain=PeriodicDomain() ) # discontinuous function space for visualization dis_func_space = fe.FunctionSpace( mesh, 'DG', INPUTS['element_degree'], constrained_domain=PeriodicDomain() ) if ARGS['--verbose']: print('Number of cells:', mesh.num_cells()) print('Number of faces:', mesh.num_faces()) print('Number of edges:', mesh.num_edges()) print('Number of vertices:', mesh.num_vertices()) print('Number of DOFs:', len(func_space.dofmap().dofs())) # temperature/concentration field field = fe.TrialFunction(func_space) # test function test_func = fe.TestFunction(func_space) # function, which is equal to 1 everywhere unit_function = fe.Function(func_space) unit_function.assign(fe.Constant(1.0)) # assign material properties to each domain if INPUTS['mode'] == 'conductivity': mat_prop = SubdomainConstant( subdomains, fe.Constant(INPUTS['conductivity']['gas']), fe.Constant(INPUTS['conductivity']['solid']), degree=0 ) elif INPUTS['mode'] == 'diffusivity': mat_prop = SubdomainConstant( subdomains, fe.Constant(INPUTS['diffusivity']['gas']), fe.Constant(INPUTS['diffusivity']['solid']) * fe.Constant(INPUTS['solubility'] * gas_constant * INPUTS['temperature']), degree=0 ) # assign 1 to gas domain, and 0 to solid domain gas_content = SubdomainConstant( subdomains, fe.Constant(1.0), fe.Constant(0.0), degree=0 ) # define structure of foam over whole domain structure = fe.project(unit_function * gas_content, dis_func_space) # calculate porosity and wall thickness porosity = fe.assemble(structure * fe.dx) / ((XMAX - XMIN) * (YMAX - YMIN) * (ZMAX - ZMIN)) print('Porosity: {0}'.format(porosity)) dwall = wall_thickness( porosity, INPUTS['morphology']['cell_size'], INPUTS['morphology']['strut_content']) print('Wall thickness: {0} m'.format(dwall)) # calculate effective conductivity/diffusivity by analytical model if INPUTS['mode'] == 'conductivity': eff_prop = analytical_conductivity( INPUTS['conductivity']['gas'], INPUTS['conductivity']['solid'], porosity, INPUTS['morphology']['strut_content']) print('Analytical model: {0} W/(mK)'.format(eff_prop)) elif INPUTS['mode'] == 'diffusivity': eff_prop = analytical_diffusivity( INPUTS['diffusivity']['solid'] * INPUTS['solubility'], INPUTS['solubility'], porosity, INPUTS['morphology']['cell_size'], dwall, INPUTS['temperature'], INPUTS['morphology']['enhancement_par']) print('Analytical model: {0} m^2/s'.format(eff_prop)) # create system matrix system_matrix = -mat_prop * \ fe.inner(fe.grad(field), fe.grad(test_func)) * fe.dx left_side, right_side = fe.lhs(system_matrix), fe.rhs(system_matrix) # define boundary conditions bcs = [ fe.DirichletBC(func_space, fe.Constant( INPUTS['boundary_conditions']['top']), top_bc), fe.DirichletBC(func_space, fe.Constant( INPUTS['boundary_conditions']['bottom']), bottom_bc) ] # compute solution field = fe.Function(func_space) fe.solve(left_side == right_side, field, bcs) # output temperature/concentration at the boundaries if ARGS['--verbose']: print('Checking periodicity:') print('Value at XMIN:', field(XMIN, (YMIN + YMAX) / 3, (ZMIN + ZMAX) / 3)) print('Value at XMAX:', field(XMAX, (YMIN + YMAX) / 3, (ZMIN + ZMAX) / 3)) print('Value at YMIN:', field((XMIN + XMAX) / 3, YMIN, (ZMIN + ZMAX) / 3)) print('Value at YMAX:', field((XMIN + XMAX) / 3, YMAX, (ZMIN + ZMAX) / 3)) print('Value at ZMIN:', field((XMIN + XMAX) / 3, (YMIN + YMAX) / 3, ZMIN)) print('Value at ZMAX:', field((XMIN + XMAX) / 3, (YMIN + YMAX) / 3, ZMAX)) # calculate flux, and effective properties vec_func_space = fe.VectorFunctionSpace( mesh, INPUTS['element_type'], INPUTS['element_degree'] ) flux = fe.project(-mat_prop * fe.grad(field), vec_func_space) divergence = fe.project(-fe.div(mat_prop * fe.grad(field)), func_space) flux_x, flux_y, flux_z = flux.split() av_flux = fe.assemble(flux_z * fe.dx) / ((XMAX - XMIN) * (YMAX - YMIN)) eff_prop = av_flux * (ZMAX - ZMIN) / ( INPUTS['boundary_conditions']['top'] - INPUTS['boundary_conditions']['bottom'] ) if INPUTS['mode'] == 'conductivity': print('Numerical model: {0} W/(mK)'.format(eff_prop)) elif INPUTS['mode'] == 'diffusivity': print('Numerical model: {0} m^2/s'.format(eff_prop)) # projection of concentration has to be in discontinuous function space if INPUTS['mode'] == 'diffusivity': sol_field = SubdomainConstant( subdomains, fe.Constant(1.0), fe.Constant(INPUTS['solubility'] * gas_constant * INPUTS['temperature']), degree=0 ) field = fe.project(field * sol_field, dis_func_space) # save results with open(fname + "_eff_prop.csv", 'w') as textfile: textfile.write('eff_prop\n') textfile.write('{0}\n'.format(eff_prop)) fe.File(fname + "_solution.pvd") << field fe.File(fname + "_structure.pvd") << structure if INPUTS['saving']['flux']: fe.File(fname + "_flux.pvd") << flux if INPUTS['saving']['flux_divergence']: fe.File(fname + "_flux_divergence.pvd") << divergence if INPUTS['saving']['flux_components']: fe.File(fname + "_flux_x.pvd") << flux_x fe.File(fname + "_flux_y.pvd") << flux_y fe.File(fname + "_flux_z.pvd") << flux_z # plot results if INPUTS['plotting']['solution']: fe.plot(field, title="Solution") if INPUTS['plotting']['flux']: fe.plot(flux, title="Flux") if INPUTS['plotting']['flux_divergence']: fe.plot(divergence, title="Divergence") if INPUTS['plotting']['flux_components']: fe.plot(flux_x, title='x-component of flux (-kappa*grad(u))') fe.plot(flux_y, title='y-component of flux (-kappa*grad(u))') fe.plot(flux_z, title='z-component of flux (-kappa*grad(u))') if True in INPUTS['plotting'].values(): fe.interactive() print( term.yellow + "End." + term.normal )
def strain(v): return fn.sym(fn.grad(v))
def naive_linearization(d_, w_, k): E = grad(d_["n"]) + grad(d_["n"]).T \ + grad(d_["n-1"]).T*grad(d_["n"]) return 0.5 * E
def eps(v): return fnc.sym(fnc.grad(v))
def cn_before_ab(d_, w_, k): E = 0.5*(grad(d_["n"]).T + grad(d_["n-1"]).T + grad(d_["n"]) + grad(d_["n-1"])) \ + 0.5*((grad(d_["n-1"] + k*(3./2*w_["n-1"] - 1./2*w_["n-2"])).T * grad(d_["n"])) \ + (grad(d_["n-1"]).T*grad(d_["n-1"]))) return 0.5 * E
def sigma(r): return 2.0 * mu * fnc.sym(fnc.grad(r)) + lmbda * fnc.tr( fnc.sym(fnc.grad(r))) * fnc.Identity(len(r))
# Initialize the adapter according to the specific participant if problem is ProblemType.DIRICHLET: precice = Adapter(adapter_config_filename="precice-adapter-config-D.json") precice_dt = precice.initialize(coupling_boundary, read_function_space=V, write_object=f_N_function) elif problem is ProblemType.NEUMANN: precice = Adapter(adapter_config_filename="precice-adapter-config-N.json") precice_dt = precice.initialize(coupling_boundary, read_function_space=W, write_object=u_D_function) dt = Constant(0) dt.assign(np.min([fenics_dt, precice_dt])) # Define variational problem u = TrialFunction(V) v = TestFunction(V) f = Expression('beta - 2 - 2*alpha', degree=2, alpha=alpha, beta=beta, t=0) F = u * v / dt * dx + dot(grad(u), grad(v)) * dx - (u_n / dt + f) * v * dx bcs = [DirichletBC(V, u_D, remaining_boundary)] # Set boundary conditions at coupling interface once wrt to the coupling # expression coupling_expression = precice.create_coupling_expression() if problem is ProblemType.DIRICHLET: # modify Dirichlet boundary condition on coupling interface bcs.append(DirichletBC(V, coupling_expression, coupling_boundary)) if problem is ProblemType.NEUMANN: # modify Neumann boundary condition on coupling interface, modify weak # form correspondingly F += v * coupling_expression * dolfin.ds a, L = lhs(F), rhs(F)
def k(u, w): return fnc.inner(sigma(u), fnc.sym(fnc.grad(w))) * fnc.dx
inclusion = Inclusion_3d() point0 = "near(x[0], 0) && near(x[1], 0) && near(x[2], 0)" V = FunctionSpace(mesh, "CG", order, constrained_domain=PeriodicBoundary(dim)) # setting the elements that lies in inclusion and in matrix phase domains = MeshFunction("size_t", mesh, dim) domains.set_all(0) inclusion.mark(domains, 1) dx = Measure('dx', subdomain_data=domains) def bilf(up, vp): # bilinear form return inner(mat * up, vp) * dx(0) + inner(inc * up, vp) * dx(1) bc0 = DirichletBC(V, Constant(0.), point0, method='pointwise') # SOLVER u = TrialFunction(V) v = TestFunction(V) uE = Function(V) solve(bilf(grad(u), grad(v)) == -bilf(E, grad(v)), uE, bcs=[bc0]) # POSTPROCESSING evaluation of guaranteed bound AH11 = assemble(bilf(grad(uE) + E, grad(uE) + E)) print('homogenised component A11 = {} (FEM)'.format(AH11)) print('END')
def staggered_solve(self): self.U = fe.VectorFunctionSpace(self.mesh, 'CG', 1) self.W = fe.FunctionSpace(self.mesh, 'CG', 1) self.WW = fe.FunctionSpace(self.mesh, 'DG', 0) self.eta = fe.TestFunction(self.U) self.zeta = fe.TestFunction(self.W) del_x = fe.TrialFunction(self.U) del_d = fe.TrialFunction(self.W) self.x_new = fe.Function(self.U) self.d_new = fe.Function(self.W) x_old = fe.Function(self.U) d_old = fe.Function(self.W) self.H_old = fe.Function(self.WW) self.build_weak_form_staggered() J_u = fe.derivative(self.G_u, self.x_new, del_x) J_d = fe.derivative(self.G_d, self.d_new, del_d) self.set_bcs_staggered() p_u = fe.NonlinearVariationalProblem(self.G_u, self.x_new, self.BC_u, J_u) p_d = fe.NonlinearVariationalProblem(self.G_d, self.d_new, self.BC_d, J_d) solver_u = fe.NonlinearVariationalSolver(p_u) solver_d = fe.NonlinearVariationalSolver(p_d) vtkfile_u = fe.File('data/pvd/{}/u.pvd'.format(self.case_name)) vtkfile_d = fe.File('data/pvd/{}/d.pvd'.format(self.case_name)) for i, (disp, rp) in enumerate( zip(self.displacements, self.relaxation_parameters)): print('\n') print( '=================================================================================' ) print('>> Step {}, disp boundary condition = {} [mm]'.format( i, disp)) print( '=================================================================================' ) self.H_old.assign( fe.project( history(self.H_old, self.psi(strain(fe.grad(self.x_new))), self.psi_cr), self.WW)) self.presLoad.t = disp newton_prm = solver_u.parameters['newton_solver'] newton_prm['maximum_iterations'] = 100 newton_prm['absolute_tolerance'] = 1e-4 newton_prm['relaxation_parameter'] = rp iteration = 0 err = 1. while err > self.staggered_tol: iteration += 1 solver_d.solve() solver_u.solve() err_u = fe.errornorm(self.x_new, x_old, norm_type='l2', mesh=None) err_d = fe.errornorm(self.d_new, d_old, norm_type='l2', mesh=None) err = max(err_u, err_d) x_old.assign(self.x_new) d_old.assign(self.d_new) print( '---------------------------------------------------------------------------------' ) print('>> iteration. {}, error = {:.5}'.format(iteration, err)) print( '---------------------------------------------------------------------------------' ) if err < self.staggered_tol or iteration >= self.staggered_maxiter: print( '=================================================================================' ) print('\n') self.x_new.rename("u", "u") self.d_new.rename("d", "d") vtkfile_u << self.x_new vtkfile_d << self.d_new break force_upper = float(fe.assemble(self.sigma[1, 1] * self.ds(1))) print("Force upper {}".format(force_upper)) self.delta_u_recorded.append(disp) self.sigma_recorded.append(force_upper)
# old results uold = fn.interpolate(uinit, Mh) vold = fn.interpolate(fn.Constant(b * pow(a + b, -2)), Mh) # computation parameters hsize = 1.0 / nps t = 0.0 CFL = 5.0 dt = CFL * hsize * hsize T = 2.0 frequencySave = 100 # weak form Left = u/dt * uT * fn.dx + v/dt * vT * fn.dx \ + c1 * fn.inner(fn.grad(u), fn.grad(uT)) * fn.dx \ + c2 * fn.inner(fn.grad(v), fn.grad(vT)) * fn.dx Right = uold * uT/dt * fn.dx + vold * vT/dt * fn.dx \ + d * (a - uold + uold * uold * vold) * uT * fn.dx \ + d * (b - uold * uold * vold) * vT * fn.dx AA = fn.assemble(Left) solver = fn.LUSolver(AA) solver.parameters["reuse_factorization"] = True # time loop inc = 0 while (t <= T):
def monolithic_solve(self): self.U = fe.VectorElement('CG', self.mesh.ufl_cell(), 1) self.W = fe.FiniteElement("CG", self.mesh.ufl_cell(), 1) self.M = fe.FunctionSpace(self.mesh, self.U * self.W) self.WW = fe.FunctionSpace(self.mesh, 'DG', 0) m_test = fe.TestFunctions(self.M) m_delta = fe.TrialFunctions(self.M) m_new = fe.Function(self.M) self.eta, self.zeta = m_test self.x_new, self.d_new = fe.split(m_new) self.H_old = fe.Function(self.WW) vtkfile_u = fe.File('data/pvd/{}/u.pvd'.format(self.case_name)) vtkfile_d = fe.File('data/pvd/{}/d.pvd'.format(self.case_name)) self.build_weak_form_monolithic() dG = fe.derivative(self.G, m_new) self.set_bcs_monolithic() p = fe.NonlinearVariationalProblem(self.G, m_new, self.BC, dG) solver = fe.NonlinearVariationalSolver(p) for i, (disp, rp) in enumerate( zip(self.displacements, self.relaxation_parameters)): print('\n') print( '=================================================================================' ) print('>> Step {}, disp boundary condition = {} [mm]'.format( i, disp)) print( '=================================================================================' ) self.H_old.assign( fe.project( history(self.H_old, self.psi(strain(fe.grad(self.x_new))), self.psi_cr), self.WW)) self.presLoad.t = disp newton_prm = solver.parameters['newton_solver'] newton_prm['maximum_iterations'] = 100 newton_prm['absolute_tolerance'] = 1e-4 newton_prm['relaxation_parameter'] = rp solver.solve() self.x_plot, self.d_plot = m_new.split() self.x_plot.rename("u", "u") self.d_plot.rename("d", "d") vtkfile_u << self.x_plot vtkfile_d << self.d_plot force_upper = float(fe.assemble(self.sigma[1, 1] * self.ds(1))) print("Force upper {}".format(force_upper)) self.delta_u_recorded.append(disp) self.sigma_recorded.append(force_upper) print( '=================================================================================' )
def update_history(self): psi_new = self.psi_plus(strain(fe.grad(self.x_new))) return psi_new
def get_new_value(self, r: fenics.Function) -> fenics.Expression: return 2.0*self.lame_mu*fenics.sym(fenics.grad(r)) \ + self.lame_lambda*fenics.tr(fenics.sym(fenics.grad(r)))*fenics.Identity(len(r))
def boundary(x, on_boundary): return on_boundary bc = fs.DirichletBC(V, u_D, boundary) # Define initial value u_0 = fs.Expression('exp(-a * pow(x[0], 2) - a * pow(x[1], 2))', degree=2, a=5) u_n = fs.interpolate(u_0, V) # Define variational problem u = fs.TrialFunction(V) v = fs.TestFunction(V) f = fs.Constant(0) F = u * v * fs.dx + dt * fs.dot(fs.grad(u), fs.grad(v)) *fs.dx - (u_n + dt * f) * v * fs.dx a, L = fs.lhs(F), fs.rhs(F) # Create VTK file for saving solution vtkfile = fs.File('heat_gaussian/solution.pvd') # Time-stepping u = fs.Function(V) t = 0 for n in range(num_steps): # Update current time t += dt # Compute solution fs.solve(a == L, u, bc)
def ab_on_F(d_, w_, k): F1 = grad(1.5 * d_["n-1"] - 0.5 * d_["n-2"]) - Identity(2) F2 = 0.5 * grad(d_["n"] + d_["n-1"]) E = F1.T * F2 - I return 0.5 * E
def test_formulation_1_trap_2_materials(): ''' Test function formulation() with 1 intrinsic trap and 2 materials ''' def create_subdomains(x1, x2): class domain(FESTIM.SubDomain): def inside(self, x, on_boundary): return x[0] >= x1 and x[0] <= x2 domain = domain() return domain dt = 1 traps = [{ "energy": 1, "density": 2, "materials": [1, 2] }] materials = [{ "alpha": 1, "beta": 2, "density": 3, "borders": [0, 0.5], "E_diff": 4, "D_0": 5, "id": 1 }, { "alpha": 2, "beta": 3, "density": 4, "borders": [0.5, 1], "E_diff": 5, "D_0": 6, "id": 2 }] extrinsic_traps = [] mesh = fenics.UnitIntervalMesh(10) mf = fenics.MeshFunction("size_t", mesh, 1, 1) mat1 = create_subdomains(0, 0.5) mat2 = create_subdomains(0.5, 1) mat1.mark(mf, 1) mat2.mark(mf, 2) V = fenics.VectorFunctionSpace(mesh, 'P', 1, 2) u = fenics.Function(V) u_n = fenics.Function(V) v = fenics.TestFunction(V) solutions = list(fenics.split(u)) previous_solutions = list(fenics.split(u_n)) testfunctions = list(fenics.split(v)) mf = fenics.MeshFunction('size_t', mesh, 1, 1) dx = fenics.dx(subdomain_data=mf) temp = fenics.Expression("300", degree=0) flux_ = fenics.Expression("1", degree=0) F, expressions = FESTIM.formulation( traps, extrinsic_traps, solutions, testfunctions, previous_solutions, dt, dx, materials, temp, flux_) # Transient sol expected_form = ((solutions[0] - previous_solutions[0]) / dt) * \ testfunctions[0]*dx # Diffusion sol mat 1 expected_form += 5 * fenics.exp(-4/8.6e-5/temp) * \ fenics.dot( fenics.grad(solutions[0]), fenics.grad(testfunctions[0]))*dx(1) # Diffusion sol mat 2 expected_form += 6 * fenics.exp(-5/8.6e-5/temp) * \ fenics.dot( fenics.grad(solutions[0]), fenics.grad(testfunctions[0]))*dx(2) # Source sol expected_form += -flux_*testfunctions[0]*dx # Transient trap 1 expected_form += ((solutions[1] - previous_solutions[1]) / dt) * \ testfunctions[1]*dx # Trapping trap 1 mat 1 expected_form += - 5 * fenics.exp(-4/8.6e-5/temp)/1/1/2 * \ solutions[0] * (2 - solutions[1]) * \ testfunctions[1]*dx(1) # Trapping trap 1 mat 2 expected_form += - 6 * fenics.exp(-5/8.6e-5/temp)/2/2/3 * \ solutions[0] * (2 - solutions[1]) * \ testfunctions[1]*dx(2) # Detrapping trap 1 mat 1 expected_form += 1e13*fenics.exp(-1/8.6e-5/temp)*solutions[1] * \ testfunctions[1]*dx(1) # Detrapping trap 1 mat 2 expected_form += 1e13*fenics.exp(-1/8.6e-5/temp)*solutions[1] * \ testfunctions[1]*dx(2) # Source detrapping sol expected_form += ((solutions[1] - previous_solutions[1]) / dt) * \ testfunctions[0]*dx assert expected_form.equals(F) is True
def solve(self): # TODO: when FEniCS ported to Python3, this should be exist_ok try: os.makedirs('results') except OSError: pass z, w = (self.z, self.w) u0 = d.Constant(0.0) # Define the linear and bilinear forms L = u0 * w * dx # Define useful functions cond = d.Function(self.DV) U = d.Function(self.V) # Initialize the max_e vector, that will store the cumulative max e values max_e = d.Function(self.V) max_e.vector()[:] = 0.0 max_e.rename("max_E", "Maximum energy deposition by location") max_e_file = d.File("results/%s-max_e.pvd" % input_mesh) max_e_per_step = d.Function(self.V) max_e_per_step_file = d.File("results/%s-max_e_per_step.pvd" % input_mesh) self.es = {} self.max_es = {} fi = d.File("results/%s-cond.pvd" % input_mesh) potential_file = d.File("results/%s-potential.pvd" % input_mesh) # Loop through the voltages and electrode combinations for i, (anode, cathode, voltage) in enumerate(v.electrode_triples): print("Electrodes %d (%lf) -> %d (0)" % (anode, voltage, cathode)) cond = d.project(self.sigma_start, V=self.DV) # Define the Dirichlet boundary conditions on the active needles uV = d.Constant(voltage) term1_bc = d.DirichletBC(self.V, uV, self.patches, v.needles[anode]) term2_bc = d.DirichletBC(self.V, u0, self.patches, v.needles[cathode]) e = d.Function(self.V) e.vector()[:] = max_e.vector() # Re-evaluate conductivity self.increase_conductivity(cond, e) for j in range(v.max_restarts): # Update the bilinear form a = d.inner(d.nabla_grad(z), cond * d.nabla_grad(w)) * dx # Solve again print(" [solving...") d.solve(a == L, U, bcs=[term1_bc, term2_bc]) print(" ....solved]") # Extract electric field norm for k in range(len(U.vector())): if N.isnan(U.vector()[k]): U.vector()[k] = 1e5 e_new = d.project(d.sqrt(d.dot(d.grad(U), d.grad(U))), self.V) # Take the max of the new field and the established electric field e.vector()[:] = N.array([max(*X) for X in zip(e.vector(), e_new.vector())]) # Re-evaluate conductivity fi << cond self.increase_conductivity(cond, e) potential_file << U # Save the max e function to a VTU max_e_per_step.vector()[:] = e.vector()[:] max_e_per_step_file << max_e_per_step # Store this electric field norm, for this triple, for later reference self.es[i] = e # Store the max of this electric field norm and that for all previous triples max_e_array = N.array([max(*X) for X in zip(max_e.vector(), e.vector())]) max_e.vector()[:] = max_e_array # Create a new max_e function for storage, or it will be overwritten by the next iteration max_e_new = d.Function(self.V) max_e_new.vector()[:] = max_e_array # Store this max e function for the cumulative coverage curve calculation later self.max_es[i] = max_e_new # Save the max e function to a VTU max_e_file << max_e self.max_e_count = i