def _solve_cell_problems(self): # Solves the cell problems (one for each space dimension) w = fe.TrialFunction(self.function_space) v = fe.TestFunction(self.function_space) a = self.a_y * fe.dot(fe.grad(w), fe.grad(v)) * fe.dx for i in range(self.dim): L = fe.div(self.a_y * self.e_is[i]) * v * fe.dx bc = fe.DirichletBC(self.function_space, self.bc_function, PoissonSolver.boundary) fe.solve(a == L, self.cell_solutions[i], bc) fe.plot(self.cell_solutions[i])
def compute_shape_derivative(self): """Computes the part of the shape derivative that comes from the regularization Returns ------- ufl.form.Form The weak form of the shape derivative coming from the regularization """ V = self.form_handler.test_vector_field if self.has_regularization: n = fenics.FacetNormal(self.form_handler.mesh) I = fenics.Identity(self.form_handler.mesh.geometric_dimension()) self.shape_form = Constant(self.mu_surface) * ( self.current_surface - Constant(self.target_surface)) * t_div( V, n) * self.ds if not self.measure_hole: self.shape_form += Constant(self.mu_volume) * ( self.current_volume - Constant(self.target_volume)) * div(V) * self.dx self.shape_form += Constant(self.mu_barycenter)*(self.current_barycenter_x - Constant(self.target_barycenter_list[0]))\ *(self.current_barycenter_x/self.current_volume*div(V) + 1/self.current_volume*(V[0] + self.spatial_coordinate[0]*div(V)))*self.dx \ + Constant(self.mu_barycenter)*(self.current_barycenter_y - Constant(self.target_barycenter_list[1]))\ *(self.current_barycenter_y/self.current_volume*div(V) + 1/self.current_volume*(V[1] + self.spatial_coordinate[1]*div(V)))*self.dx if self.form_handler.mesh.geometric_dimension() == 3: self.shape_form += Constant(self.mu_barycenter)*(self.current_barycenter_z - Constant(self.target_barycenter_list[2]))\ *(self.current_barycenter_z/self.current_volume*div(V) + 1/self.current_volume*(V[2] + self.spatial_coordinate[2]*div(V)))*self.dx else: self.shape_form -= Constant(self.mu_volume) * ( self.current_volume - Constant(self.target_volume)) * div(V) * self.dx self.shape_form += Constant(self.mu_barycenter)*(self.current_barycenter_x - Constant(self.target_barycenter_list[0]))\ *(self.current_barycenter_x/self.current_volume*div(V) - 1/self.current_volume*(V[0] + self.spatial_coordinate[0]*div(V)))*self.dx \ + Constant(self.mu_barycenter)*(self.current_barycenter_y - Constant(self.target_barycenter_list[1]))\ *(self.current_barycenter_y/self.current_volume*div(V) - 1/self.current_volume*(V[1] + self.spatial_coordinate[1]*div(V)))*self.dx if self.form_handler.mesh.geometric_dimension() == 3: self.shape_form += Constant(self.mu_barycenter)*(self.current_barycenter_z - Constant(self.target_barycenter_list[2]))\ *(self.current_barycenter_z/self.current_volume*div(V) - 1/self.current_volume*(V[2] + self.spatial_coordinate[2]*div(V)))*self.dx return self.shape_form else: dim = self.form_handler.mesh.geometric_dimension() return inner(fenics.Constant([0] * dim), V) * self.dx
def t_div(u, n): """Computes the tangential divergence Parameters ---------- u : dolfin.function.function.Function the argument n : ufl.geometry.FacetNormal the outer unit normal vector Returns ------- ufl.core.expr.Expr the tangential divergence of u """ return fenics.div(u) - fenics.inner(fenics.grad(u) * n, n)
def postprocess(fname, field, cond): """Postprocessing of the simulation.""" func_space = field.function_space() mesh = func_space.mesh() degree = func_space.ufl_element().degree() vec_func_space = fe.VectorFunctionSpace(mesh, INPUTS['element_type'], degree) flux = fe.project(-cond * fe.grad(field), vec_func_space) divergence = fe.project(-fe.div(cond * 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)) keff = av_flux * (ZMAX - ZMIN) / (INPUTS['boundary_conditions']['top'] - INPUTS['boundary_conditions']['bottom']) print('Effective conductivity: {0}'.format(keff)) with open(fname + "_keff.csv", 'w') as textfile: textfile.write('keff\n') textfile.write('{0}\n'.format(keff)) fe.File(fname + "_solution.pvd") << field 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 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()
W.sub(0), fe.Expression(('%s * pow((x[1]) / 2.5, 2)' % RE, '0'), degree=DEG), dbc_inflow) #bc_inflow = fe.DirichletBC(W.sub(0), fe.Constant((RE, '0')), dbc_inflow) bc_p = fe.DirichletBC(W.sub(1), bc_p, dbc_top) def Max(a, b): return (a + b + abs(a - b)) / 2. def Min(a, b): return (a + b - abs(a - b)) / 2. 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 sij = 0.5 * (fe.grad(u) + fe.grad(u).T) nu_tv = lmx**(2 * fe.inner(sij, sij))**(0.5) ns_tv = fe.inner((nu_tv) * fe.grad(v), fe.grad(u)) * fe.dx ns_visc = nu * fe.inner(fe.grad(v), fe.grad(u)) * fe.dx ns_conti = q * fe.div(u) * fe.dx ns_forcing = fe.dot(v, b) * fe.dx NS = ns_conv + ns_press + ns_tv + ns_visc + ns_conti + ns_forcing N = 5 fe.parameters["form_compiler"]["quadrature_degree"] = N weakForm = (1.0 / dt) * fe.inner(u - u0, v) * fe.dx + NS
FooT = fn.CompiledSubDomain( "(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[1], 0.0) ) && 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 forms ********** # 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 fn.solve(PLeft == PRight, Sol, bcs) u, phi, p = Sol.split()
#r =fe.Constant(1) #r = nu_trial / (Stilde * kappa * kappa * d * d) r = Max(Min(nu_trial / (Stilde * kappa * kappa * d * d), fe.Constant(10)), -10) #r = fe.Constant(0.1) #g = fe.Constant(0.01) g = r + Cw2 * (r * r * r * r * r * r - r) #fw = g * ((1 + Cw3 * Cw3 * Cw3 * Cw3 * Cw3 * Cw3) / (g * g * g * g * g * g + Cw3 * Cw3 * Cw3 * Cw3 * Cw3 * Cw3)) fw = fe.elem_pow( 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.)) #fw = fe.Constant(1) 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: ns_tv = fe.inner((fv1 * nu_trial) * fe.grad(v), fe.grad(u)) * fe.dx else: sij = 0.5 * (fe.grad(u) + fe.grad(u).T) nu_tv = lmx**(2 * fe.inner(sij, sij))**(0.5) ns_tv = fe.inner((nu_tv) * fe.grad(v), fe.grad(u)) * fe.dx ns_visc = nu * fe.inner(fe.grad(v), fe.grad(u)) * fe.dx ns_conti = q * fe.div(u) * fe.dx ns_forcing = fe.dot(v, b) * fe.dx NS = ns_conv + ns_press + ns_tv + ns_visc + ns_conti + ns_forcing N = 5 fe.parameters["form_compiler"]["quadrature_degree"] = N if MODEL:
def sigma(u, p): return 2*mu*epsilon(u) - p*fs.Identity(len(u)) # Define variational problem for step 1 (Tentative velocity step) F1 = rho*fs.dot((u - u_n) / k, v)*fs.dx + \ rho*fs.dot(fs.dot(u_n, fs.nabla_grad(u_n)), v)*fs.dx \ + fs.inner(sigma(U, p_n), epsilon(v))*fs.dx \ + fs.dot(p_n*n, v)*fs.ds - fs.dot(mu*fs.nabla_grad(U)*n, v)*fs.ds \ - fs.dot(f, v)*fs.dx a1 = fs.lhs(F1) L1 = fs.rhs(F1) # Define variational problem for step 2 (Pressure correction step) a2 = fs.dot(fs.nabla_grad(p), fs.nabla_grad(q))*fs.dx L2 = fs.dot(fs.nabla_grad(p_n), fs.nabla_grad(q))*fs.dx \ - (1/k)*fs.div(u_)*q*fs.dx # Define variational problem for step 3 (Velocity correction step) a3 = fs.dot(u, v)*fs.dx L3 = fs.dot(u_, v)*fs.dx - k*fs.dot(fs.nabla_grad(p_ - p_n), v)*fs.dx # Assemble matrices A1 = fs.assemble(a1) A2 = fs.assemble(a2) A3 = fs.assemble(a3) # Apply boundary conditions to matrices [bc.apply(A1) for bc in bcu] [bc.apply(A2) for bc in bcp] # Time-stepping
def __compute_shape_gradient_forms(self): """Calculates the necessary left-hand-sides for the shape gradient problem. Returns ------- None """ self.shape_bdry_def = json.loads( self.config.get('ShapeGradient', 'shape_bdry_def', fallback='[]')) if not type(self.shape_bdry_def) == list: raise ConfigError('ShapeGradient', 'shape_bdry_def', 'The input has to be a list.') # if not len(self.shape_bdry_def) > 0: # raise ConfigError('ShapeGradient', 'shape_bdry_def','The input must not be empty.') self.shape_bdry_fix = json.loads( self.config.get('ShapeGradient', 'shape_bdry_fix', fallback='[]')) if not type(self.shape_bdry_def) == list: raise ConfigError('ShapeGradient', 'shape_bdry_fix', 'The input has to be a list.') self.shape_bdry_fix_x = json.loads( self.config.get('ShapeGradient', 'shape_bdry_fix_x', fallback='[]')) if not type(self.shape_bdry_fix_x) == list: raise ConfigError('ShapeGradient', 'shape_bdry_fix_x', 'The input has to be a list.') self.shape_bdry_fix_y = json.loads( self.config.get('ShapeGradient', 'shape_bdry_fix_y', fallback='[]')) if not type(self.shape_bdry_fix_y) == list: raise ConfigError('ShapeGradient', 'shape_bdry_fix_y', 'The input has to be a list.') self.shape_bdry_fix_z = json.loads( self.config.get('ShapeGradient', 'shape_bdry_fix_z', fallback='[]')) if not type(self.shape_bdry_fix_z) == list: raise ConfigError('ShapeGradient', 'shape_bdry_fix_z', 'The input has to be a list.') self.bcs_shape = create_bcs_list( self.deformation_space, fenics.Constant([0] * self.deformation_space.ufl_element().value_size()), self.boundaries, self.shape_bdry_fix) self.bcs_shape += create_bcs_list(self.deformation_space.sub(0), fenics.Constant(0.0), self.boundaries, self.shape_bdry_fix_x) self.bcs_shape += create_bcs_list(self.deformation_space.sub(1), fenics.Constant(0.0), self.boundaries, self.shape_bdry_fix_y) if self.deformation_space.num_sub_spaces() == 3: self.bcs_shape += create_bcs_list(self.deformation_space.sub(2), fenics.Constant(0.0), self.boundaries, self.shape_bdry_fix_z) self.CG1 = fenics.FunctionSpace(self.mesh, 'CG', 1) self.DG0 = fenics.FunctionSpace(self.mesh, 'DG', 0) if self.shape_scalar_product is None: # Use the default linear elasticity approach self.mu_lame = fenics.Function(self.CG1) self.lambda_lame = self.config.getfloat('ShapeGradient', 'lambda_lame', fallback=0.0) self.damping_factor = self.config.getfloat('ShapeGradient', 'damping_factor', fallback=0.0) if self.config.getboolean('ShapeGradient', 'inhomogeneous', fallback=False): self.volumes = fenics.project(fenics.CellVolume(self.mesh), self.DG0) vol_max = np.max(np.abs(self.volumes.vector()[:])) self.volumes.vector()[:] /= vol_max else: self.volumes = fenics.Constant(1.0) def eps(u): return fenics.Constant(0.5) * (fenics.grad(u) + fenics.grad(u).T) trial = fenics.TrialFunction(self.deformation_space) test = fenics.TestFunction(self.deformation_space) self.riesz_scalar_product = fenics.Constant(2)*self.mu_lame/self.volumes*fenics.inner(eps(trial), eps(test))*self.dx \ + fenics.Constant(self.lambda_lame)/self.volumes*fenics.div(trial)*fenics.div(test)*self.dx \ + fenics.Constant(self.damping_factor)/self.volumes*fenics.inner(trial, test)*self.dx else: # Use the scalar product supplied by the user self.riesz_scalar_product = self.shape_scalar_product
def navierStokes(projectId, mesh, faceSets, boundarySets, config): log("Navier Stokes Analysis has started") # this is the default directory, when user request for download all files in this directory is being compressed and sent to the user resultDir = "./Results/" if len(config["steps"]) > 1: return "more than 1 step is not supported yet" # config is a dictionary containing all the user inputs for solver configurations t_init = 0.0 t_final = float(config['steps'][0]["finalTime"]) t_num = int(config['steps'][0]["iterationNo"]) dt = ((t_final - t_init) / t_num) t = t_init # # Viscosity coefficient. # nu = float(config['materials'][0]["viscosity"]) rho = float(config['materials'][0]["density"]) # # Declare Finite Element Spaces # do not use triangle directly P2 = fn.VectorElement("P", mesh.ufl_cell(), 2) P1 = fn.FiniteElement("P", mesh.ufl_cell(), 1) TH = fn.MixedElement([P2, P1]) V = fn.VectorFunctionSpace(mesh, "P", 2) Q = fn.FunctionSpace(mesh, "P", 1) W = fn.FunctionSpace(mesh, TH) # # Declare Finite Element Functions # (u, p) = fn.TrialFunctions(W) (v, q) = fn.TestFunctions(W) w = fn.Function(W) u0 = fn.Function(V) p0 = fn.Function(Q) # # Macros needed for weak formulation. # def contract(u, v): return fn.inner(fn.nabla_grad(u), fn.nabla_grad(v)) def b(u, v, w): return 0.5 * (fn.inner(fn.dot(u, fn.nabla_grad(v)), w) - fn.inner(fn.dot(u, fn.nabla_grad(w)), v)) # Define boundaries bcs = [] for BC in config['BCs']: if BC["boundaryType"] == "wall": for edge in json.loads(BC["edges"]): bcs.append( fn.DirichletBC(W.sub(0), fn.Constant((0.0, 0.0, 0.0)), boundarySets, int(edge), method='topological')) if BC["boundaryType"] == "inlet": vel = json.loads(BC['value']) for edge in json.loads(BC["edges"]): bcs.append( fn.DirichletBC(W.sub(0), fn.Expression( (str(vel[0]), str(vel[1]), str(vel[2])), degree=2), boundarySets, int(edge), method='topological')) if BC["boundaryType"] == "outlet": for edge in json.loads(BC["edges"]): bcs.append( fn.DirichletBC(W.sub(1), fn.Constant(float(BC['value'])), boundarySets, int(edge), method='topological')) f = fn.Constant((0.0, 0.0, 0.0)) # weak form NSE NSE = (1.0/dt)*fn.inner(u, v)*fn.dx + b(u0, u, v)*fn.dx + nu * \ contract(u, v)*fn.dx - fn.div(v)*p*fn.dx + q*fn.div(u)*fn.dx LNSE = fn.inner(f, v) * fn.dx + (1. / dt) * fn.inner(u0, v) * fn.dx velocity_file = fn.XDMFFile(resultDir + "/vel.xdmf") pressure_file = fn.XDMFFile(resultDir + "/pressure.xdmf") velocity_file.parameters["flush_output"] = True velocity_file.parameters["functions_share_mesh"] = True pressure_file.parameters["flush_output"] = True pressure_file.parameters["functions_share_mesh"] = True # # code for projecting a boundary condition into a file for visualization # # for bc in bcs: # bc.apply(w.vector()) # fn.File("para_plotting/bc.pvd") << w.sub(0) for jj in range(0, t_num): t = t + dt # print('t = ' + str(t)) A, b = fn.assemble_system(NSE, LNSE, bcs) fn.solve(A, w.vector(), b) # fn.solve(NSE==LNSE,w,bcs) fn.assign(u0, w.sub(0)) fn.assign(p0, w.sub(1)) # Save Solutions to Paraview File if (jj % 20 == 0): velocity_file.write(u0, t) pressure_file.write(p0, t) sendFile(projectId, resultDir + "vel.xdmf") sendFile(projectId, resultDir + "vel.h5") sendFile(projectId, resultDir + "pressure.xdmf") sendFile(projectId, resultDir + "pressure.h5") statusUpdate(projectId, "STARTED", {"progress": jj / t_num * 100})
if (stim_t1 <= t and t <= stim_t1 + stim_dur1): return waveS1 if (stim_t2 <= t and t <= stim_t2 + stim_dur2): return waveS2 else: return fn.Constant(0.0) # weak forms - poroelasticity # left-hand side pe_left_hand_side = \ (c0/alpha + 1.0/lmbda) * (p/dt) * q * fn.dx - \ (1.0/lmbda) * (phi/dt) * q * fn.dx + \ (kappa/(eta * alpha)) * fn.dot(fn.grad(p), fn.grad(q)) * fn.dx - \ (1.0/lmbda) * phi * psi * fn.dx + \ (1.0/lmbda) * p * psi * fn.dx - \ fn.div(u) * psi * fn.dx + \ 2.0 * mu * fn.inner(strain(u), strain(v)) * fn.dx - \ phi * fn.div(v) * fn.dx # right-hand side pe_right_hand_side = \ (c0/alpha + 1.0/lmbda) * (p_old/dt) * q * fn.dx - \ (1.0/lmbda) * (phi_old/dt) * q * fn.dx + \ fn.dot(f, v) * fn.dx + \ fn.dot(v, c_1 * fn.outer(f_0, f_0) * fn.grad(n_old)) * fn.dx # solutions pe_solution = fn.Function(Hh) rd_solution = fn.Function(Nh) z = fn.Function(Vhf)
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)
fe.Expression(('%s * pow((x[1] - 1) / 2.5, 2)' % RE, '0'), degree=DEG), dbc_inflow) #bc_inflow = fe.DirichletBC(W.sub(0), fe.Constant((RE, '0')), dbc_inflow) bc_p = fe.DirichletBC(W.sub(1), bc_p, dbc_top) def Max(a, b): return (a + b + abs(a - b)) / 2. def Min(a, b): return (a + b - abs(a - b)) / 2. 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 sij = 0.5 * (fe.grad(u) + fe.grad(u).T) S = fe.sqrt(EPSILON + 2. * fe.inner(0.5 * (fe.grad(u) + fe.grad(u).T), 0.5 * (fe.grad(u) + fe.grad(u).T))) lmx = 0.3 nu_tv = lmx**2. * S #nu_tv = 0.5 * fe.inner(sij, sij) ** 0.5 #nu_tv = lmx * (2 * fe.inner(sij, sij)) ** (0.5) #ns_tv = fe.inner((nu_tv) * fe.grad(v), fe.grad(u)) * fe.dx ns_visc = (nu + nu_tv) * fe.inner(fe.grad(v), fe.grad(u)) * fe.dx #ns_visc = nu * fe.inner(fe.grad(v), fe.grad(u)) * fe.dx ns_conti = q * fe.div(u) * fe.dx ns_forcing = fe.dot(v, b) * fe.dx
def explicit_relax_dyn(w0, kappa=1e5, dt=1.e-5, t_end=1.e-4, show_plots=False): (u0, p0, v0) = fe.split(w0) bcs_u, bcs_p, bcs_v = load_2d_muscle_bc(V_upv.sub(0), V_upv.sub(1), V_upv.sub(2), boundaries) kappa = fe.Constant(kappa) 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) + incompr_relaxation( p0, kappa) g = incompr_constr(J) # Lagrange function (without constraint) L = -W P = first_piola_stress(L, F) G = incompr_stress(g, F) (u1, p1, v1) = fe.TrialFunctions(V_upv) (eta, q, xi) = fe.TestFunctions(V_upv) a_dyn_u = inner(u1 - u0, eta) * dx - dt * inner(v1, eta) * dx a_dyn_p = (p1 - p0) * q * dx - dt * kappa * div(v1) * J * 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(p0 * G, grad(xi)) * dx - inner(B, xi) * dx) a = fe.lhs(a_dyn_u + a_dyn_p + a_dyn_v) l = fe.rhs(a_dyn_u + a_dyn_p + a_dyn_v) w1 = fe.Function(V_upv) w2 = fe.Function(V_upv) sol = [] vol = fe.assemble(1. * dx) t = 0 while t < t_end: print("progress: %f" % (100. * t / t_end)) A = fe.assemble(a) L = fe.assemble(l) for bc in bcs_u + bcs_p + bcs_v: bc.apply(A, L) fe.solve(A, w1.vector(), L) if fe.norm(w1.vector()) > 1e7: print('ERROR: norm explosion') break # update initial values for next step w0.assign(w1) 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, kappa
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 )