def updateStatistics(self): for curLevel in range(len(self.space4Level)): samples = self.y4Level[curLevel] self.variance4level[curLevel] = np.var(samples, 0) compCost = self.space4Level[curLevel].dim() ** 2 / 1000. # Simple for uniform meshes # optSamples = self.constCompCost * np.sqrt( # np.sqrt(np.sqrt(np.mean(np.abs(self.variance4level[curLevel]))) / compCost)) # Same but for general meshes space = self.space4Level[curLevel] domainArea = assemble(interpolate(Constant(1), space) * dx) varianceMean = Function(space) varianceMean.vector().set_local(np.abs(self.variance4level[curLevel])) varianceIntMean = np.sqrt(assemble(varianceMean * dx) / domainArea) optSamples = self.constCompCost * np.sqrt(np.sqrt( varianceIntMean / compCost)) # Alernate from ??? # l = curLevel + 2 # maxL = len(self.space4Level) + 1 # epsOptSamples = 0.1 # optSamples = l ** (2 + 2 * epsOptSamples) * 2 ** (2 * (maxL - l)) self.optNumSamples4Level[curLevel] = np.rint(optSamples).astype(int) self.compCost4lvl[-1] = sum(list(len(samples) * (space.dim() ** 2) for (space, samples) in zip(self.space4Level, self.y4Level)))
def local_mass_matrix(): # Define mesh mesh = UnitIntervalMesh(1) # Define function space V = FunctionSpace(mesh, "Lagrange", 1) # Define trial and test functions u = TrialFunction(V) v = TestFunction(V) # Define bilinear form a = (dot(grad(u), grad(v)) + u * v) * dx # Assemble matrix A = assemble(a) print(A.array()) # Bilinear form for just the mass matrix part a2 = u * v * dx # Assemble mass matrix A2 = assemble(a2) print(6 * A2.array())
def _assemble_system_control_diag(a, dummy, bcs, diag_value): A = PETScMatrix() assemble(a, tensor=A) dummy_vec = assemble(dummy) for bc in bcs: bc.zero(A) bc.zero_columns(A, dummy_vec, diag_value) return A
def tv_reg(lmda, mu, dx, R_lmda=1, R_mu=1, eps=1e-10): grad_lamda = grad(lmda) grad_mu = grad(mu) integrand_lmda = R_lmda * sqrt(inner(grad_lamda, grad_lamda) + eps) * dx integrand_mu = R_mu * sqrt(inner(grad_mu, grad_mu) + eps) * dx return assemble(integrand_lmda + integrand_mu)
def tn_reg(lmda, mu, dx, R_lmda=1, R_mu=1): grad_lamda = grad(lmda) grad_mu = grad(mu) reg = 0.5 * R_lmda * inner(grad_lamda, grad_lamda) * dx + \ 0.5 * R_mu * inner(grad_mu, grad_mu) * dx Reg = assemble(reg) return Reg
def estimate(self, solution): mesh = solution.function_space().mesh() # Define cell and facet residuals R_T = -(self.rhs_f + div(grad(solution))) n = FacetNormal(mesh) R_dT = dot(grad(solution), n) # Will use space of constants to localize indicator form Constants = FunctionSpace(mesh, "DG", 0) w = TestFunction(Constants) h = CellSize(mesh) # Define form for assembling error indicators form = (h ** 2 * R_T ** 2 * w * dx + avg(h) * avg(R_dT) ** 2 * 2 * avg(w) * dS) # + h * R_dT ** 2 * w * ds) # Assemble error indicators indicators = assemble(form) # Calculate error error_estimate = sqrt(sum(i for i in indicators.array())) # Take sqrt of indicators indicators = np.array([sqrt(i) for i in indicators]) # Mark cells for refinement based on maximal marking strategy largest_error = max(indicators) cell_markers = MeshFunction("bool", mesh, mesh.topology().dim()) for c in cells(mesh): cell_markers[c] = indicators[c.index()] > (self.fraction * largest_error) return error_estimate, cell_markers
def computeError4level(self, meanApprox4lvl, lastSpace, meanExact = None): if meanExact == None: solMesh = lastSpace.mesh() solFamily = lastSpace.ufl_element().family() solDegree = lastSpace.ufl_element().degree() refSpace = FunctionSpace(refine(refine(solMesh)), solFamily, solDegree) meanExact = self.solveMean(refSpace) refSpace = meanExact.function_space() error4lvl = list( np.sqrt(assemble( (project(meanApprox, refSpace) - interpolate(meanExact, refSpace)) ** 2 * dx )) for meanApprox in meanApprox4lvl) return error4lvl
def compute_error(u1, u2): # Reference mesh mesh_resolution_ref = 500 mesh_ref = UnitIntervalMesh(mesh_resolution_ref) # Reference function space V_ref = FunctionSpace(mesh_ref, "CG", 1) # Evaluate the input functions on the reference mesh Iu1 = interpolate(u1, V_ref) Iu2 = interpolate(u2, V_ref) # Compute the error e = Iu1 - Iu2 error = sqrt(assemble(e * e * dx)) return error
def plot_basis_function(): # Declare mesh and FEM functions mesh = UnitSquareMesh(10, 10) V = FunctionSpace(mesh, "CG", 1) phi = Function(V) phi.vector()[:] = 0.0 phi.vector()[10] = 1.0 # Plot the basis function fig = plt.figure() plot(phi, fig=fig) plt.show() val = assemble(phi * phi * dx) print(val)
def global_stiffness_matrix(): # Define mesh mesh = UnitIntervalMesh(10) # Define function space V = FunctionSpace(mesh, "Lagrange", 1) # Define trial and test functions u = TrialFunction(V) v = TestFunction(V) # Define bilinear form a = dot(grad(u), grad(v)) * dx # Assemble matrix A = assemble(a) h = 1 / 10 print(h * A.array())
# Defining displacement space V = VectorFunctionSpace(mesh, finiteElement.family, finiteElement.order) # Stresss space S = TensorFunctionSpace(mesh, finiteElement.family, finiteElement.order) # Trial and test functions uTrial = TrialFunction(V) w = TestFunction(V) # weak operators massOp = physics.rho*inner(uTrial, w)*dx stiffOp = inner(elasticity.stress(physics.mu, physics.lmbda, uTrial), grad(w))*dx # Assembling M = assemble(massOp) R = assemble(stiffOp) ## Create zero boundary condition #bc = DirichletBC(V, Constant(geo.nDim*[0.0]), dirichletSubdomain) ## Construct dirichlet contribution vectors #dirichletM = PETScVector(MPI_COMM_WORLD, M.size(0)) #bc.zero(M) #bc.zero_columns(M, dirichletM, 1) #dirichletR = PETScVector(MPI_COMM_WORLD, R.size(0)) #bc.zero(R) #bc.zero_columns(R, dirichletR, 1) ### ### Output configuration
def solve_navier_stokes_equation(interior_circle=True, num_mesh_refinements=0): """ Solve the Navier-Stokes equation on a hard-coded mesh with hard-coded initial and boundary conditions """ mesh, om, im, nm, ymax, sub_domains = setup_geometry( interior_circle, num_mesh_refinements) dsi = Measure("ds", domain=mesh, subdomain_data=sub_domains) # Setup FEM function spaces # Function space for the velocity V = VectorFunctionSpace(mesh, "CG", 1) # Function space for the pressure Q = FunctionSpace(mesh, "CG", 1) # Mixed function space for velocity and pressure W = V * Q # Setup FEM functions v, q = TestFunctions(W) w = Function(W) (u, p) = (as_vector((w[0], w[1])), w[2]) u0 = Function(V) # Inlet velocity uin = Expression(("4*(x[1]*(YMAX-x[1]))/(YMAX*YMAX)", "0."), YMAX=ymax, degree=1) # Viscosity and stabilization parameters nu = 1e-6 h = CellSize(mesh) d = 0.2 * h**(3.0 / 2.0) # Time parameters time_step = 0.1 t_start, t_end = 0.0, 10.0 # Penalty parameter gamma = 10 / h # Time stepping t = t_start step = 0 while t < t_end: # Time discretization (Crank–Nicolson method) um = 0.5 * u + 0.5 * u0 # Navier-Stokes equations in weak residual form (stabilized FEM) # Basic residual r = (inner((u - u0) / time_step + grad(p) + grad(um) * um, v) + nu * inner(grad(um), grad(v)) + div(um) * q) * dx # Weak boundary conditions r += gamma * (om * p * q + im * inner(u - uin, v) + nm * inner(u, v)) * ds # Stabilization r += d * (inner(grad(p) + grad(um) * um, grad(q) + grad(um) * v) + inner(div(um), div(v))) * dx # Solve the Navier-Stokes equation (one time step) solve(r == 0, w) if step % 5 == 0: # Plot norm of velocity at current time step nov = project(sqrt(inner(u, u)), Q) fig = plt.figure() plot(nov, fig=fig) plt.show() # Compute drag force on circle n = FacetNormal(mesh) drag_force_measure = p * n[0] * dsi(1) # Drag (only pressure) drag_force = assemble(drag_force_measure) print("Drag force = " + str(drag_force)) # Shift to next time step t += time_step step += 1 u0 = project(u, V)
def L2_norm(u, dx): energy = inner(u, u) * dx E = assemble(energy) return p.sqrt(E)
# Save solution in XDMF format (to be viewed in Paraview, for example) with XDMFFile(MPI.comm_world, "plane_wave.xdmf", encoding=XDMFFile.Encoding.HDF5) as file: file.write(u) ''' Calculate L2 and H1 errors of FEM solution and best approximation. This demonstrates the error bounds given in Ihlenburg. Pollution errors are evident for high wavenumbers.''' # Function space for exact solution - need it to be higher than deg V_exact = FunctionSpace(mesh, "Lagrange", deg + 3) # "exact" solution u_exact = interpolate(ui, V_exact) # best approximation from V u_BA = interpolate(ui, V) # H1 errors diff = u - u_exact diff_BA = u_BA - u_exact H1_diff = np.sqrt(assemble(inner(grad(diff), grad(diff)) * dx)) H1_BA = np.sqrt(assemble(inner(grad(diff_BA), grad(diff_BA)) * dx)) H1_exact = np.sqrt(assemble(inner(grad(u_exact), grad(u_exact)) * dx)) print('Relative H1 error of best approximation:', H1_BA / H1_exact) print('Relative H1 error of FEM solution:', H1_diff / H1_exact) # L2 errors L2_diff = np.sqrt(assemble(inner(diff, diff) * dx)) L2_BA = np.sqrt(assemble(inner(diff_BA, diff_BA) * dx)) L2_exact = np.sqrt(assemble(inner(u_exact, u_exact) * dx)) print('Relative L2 error of best approximation:', L2_BA / L2_exact) print('Relative L2 error of FEM solution:', L2_diff / L2_exact)
grad(w)) * dx # basisOp = [ inner(psi, w)*ds(i) for psi in psiBasis for i in range(geo.getNoFaces()) ] basisOp = [inner(psi, w) * ds(1) for psi in psiBasis] ## Matrices and vectors #M = PETScMatrix() #R = PETScMatrix() #P = [ PETScVector() for i in range(len(basisOp)) ] ## Assembling #assemble(massOp, tensor=M) #assemble(stiffOp, tensor=R) #[ assemble(basisOp[i], tensor=P[i]) for i in range(len(P)) ] # Assembling M = assemble(massOp) R = assemble(stiffOp) FPsi = [assemble(op) for op in basisOp] nPsi = len(FPsi) ### ### Output configuration ### outputFolder = "./new_results/" pvdFileU = [ File(outputFolder + "/" + str(i) + "/u_psi.pvd", "compressed") for i in range(nPsi) ] pvdFileV = [
def norm(v, norm_type="L2", mesh=None): """ Return the norm of a given vector or function. *Arguments* v a :py:class:`Vector <dolfin.cpp.Vector>` or a :py:class:`Function <dolfin.functions.function.Function>`. norm_type see below for alternatives. mesh optional :py:class:`Mesh <dolfin.cpp.Mesh>` on which to compute the norm. If the norm type is not specified, the standard :math:`L^2` -norm is computed. Possible norm types include: *Vectors* ================ ================= ================ Norm Usage ================ ================= ================ :math:`l^2` norm(x, 'l2') Default :math:`l^1` norm(x, 'l1') :math:`l^\infty` norm(x, 'linf') ================ ================= ================ *Functions* ================ ================= ================================= Norm Usage Includes the :math:`L^2` -term ================ ================= ================================= :math:`L^2` norm(v, 'L2') Yes :math:`H^1` norm(v, 'H1') Yes :math:`H^1_0` norm(v, 'H10') No :math:`H` (div) norm(v, 'Hdiv') Yes :math:`H` (div) norm(v, 'Hdiv0') No :math:`H` (curl) norm(v, 'Hcurl') Yes :math:`H` (curl) norm(v, 'Hcurl0') No ================ ================= ================================= *Examples of usage* .. code-block:: python v = Function(V) x = v.vector() print norm(x, 'linf') # print the infinity norm of vector x n = norm(v) # compute L^2 norm of v print norm(v, 'Hdiv') # print H(div) norm of v n = norm(v, 'H1', mesh) # compute H^1 norm of v on given mesh """ # if not isinstance(v, (GenericVector, GenericFunction)): # cpp.dolfin_error("norms.py", # "compute norm", # "expected a GenericVector or GenericFunction") # Check arguments # if not isinstance(norm_type, string_types): # cpp.dolfin_error("norms.py", # "compute norm", # "Norm type must be a string, not " + # str(type(norm_type))) # if mesh is not None and not isinstance(mesh, cpp.Mesh): # cpp.dolfin_error("norms.py", # "compute norm", # "Expecting a Mesh, not " + str(type(mesh))) # Get mesh from function if isinstance(v, cpp.function.Function) and mesh is None: mesh = v.function_space().mesh() # Define integration measure and domain dx = ufl.dx(mesh) # Select norm type if isinstance(v, cpp.la.GenericVector): return v.norm(norm_type.lower()) elif isinstance(v, ufl.Coefficient): if norm_type.lower() == "l2": M = v**2*dx elif norm_type.lower() == "h1": M = (v**2 + grad(v)**2)*dx elif norm_type.lower() == "h10": M = grad(v)**2*dx elif norm_type.lower() == "hdiv": M = (v**2 + div(v)**2)*dx elif norm_type.lower() == "hdiv0": M = div(v)**2*dx elif norm_type.lower() == "hcurl": M = (v**2 + curl(v)**2)*dx elif norm_type.lower() == "hcurl0": M = curl(v)**2*dx # else: # cpp.dolfin_error("norms.py", # "compute norm", # "Unknown norm type (\"%s\") for functions" # % str(norm_type)) # else: # cpp.dolfin_error("norms.py", # "compute norm", # "Unknown object type. Must be a vector or a function") # Assemble value r = assemble(M) # Check value if r < 0.0: pass # cpp.dolfin_error("norms.py", # "compute norm", # "Square of norm is negative, might be a round-off error") elif r == 0.0: return 0.0 else: return sqrt(r)
def norm(v, norm_type="L2", mesh=None): """ Return the norm of a given vector or function. *Arguments* v a :py:class:`Vector <dolfin.cpp.Vector>` or a :py:class:`Function <dolfin.functions.function.Function>`. norm_type see below for alternatives. mesh optional :py:class:`Mesh <dolfin.cpp.Mesh>` on which to compute the norm. If the norm type is not specified, the standard :math:`L^2` -norm is computed. Possible norm types include: *Vectors* ================ ================= ================ Norm Usage ================ ================= ================ :math:`l^2` norm(x, 'l2') Default :math:`l^1` norm(x, 'l1') :math:`l^\infty` norm(x, 'linf') ================ ================= ================ *Functions* ================ ================= ================================= Norm Usage Includes the :math:`L^2` -term ================ ================= ================================= :math:`L^2` norm(v, 'L2') Yes :math:`H^1` norm(v, 'H1') Yes :math:`H^1_0` norm(v, 'H10') No :math:`H` (div) norm(v, 'Hdiv') Yes :math:`H` (div) norm(v, 'Hdiv0') No :math:`H` (curl) norm(v, 'Hcurl') Yes :math:`H` (curl) norm(v, 'Hcurl0') No ================ ================= ================================= *Examples of usage* .. code-block:: python v = Function(V) x = v.vector() print norm(x, 'linf') # print the infinity norm of vector x n = norm(v) # compute L^2 norm of v print norm(v, 'Hdiv') # print H(div) norm of v n = norm(v, 'H1', mesh) # compute H^1 norm of v on given mesh """ if not isinstance(v, (GenericVector, GenericFunction)): raise TypeError, "expected a GenericVector or GenericFunction" # Check arguments if not isinstance(norm_type, str): cpp.dolfin_error( "norms.py", "compute norm", "Norm type must be a string, not " + str(type(norm_type))) if mesh is not None and not isinstance(mesh, Mesh): cpp.dolfin_error("norms.py", "compute norm", "Expecting a Mesh, not " + str(type(mesh))) # Select norm type if isinstance(v, GenericVector): return v.norm(norm_type.lower()) elif (isinstance(v, Coefficient) and isinstance(v, GenericFunction)): if norm_type.lower() == "l2": M = inner(v, v) * dx() elif norm_type.lower() == "h1": M = inner(v, v) * dx() + inner(grad(v), grad(v)) * dx() elif norm_type.lower() == "h10": M = inner(grad(v), grad(v)) * dx() elif norm_type.lower() == "hdiv": M = inner(v, v) * dx() + div(v) * div(v) * dx() elif norm_type.lower() == "hdiv0": M = div(v) * div(v) * dx() elif norm_type.lower() == "hcurl": M = inner(v, v) * dx() + inner(curl(v), curl(v)) * dx() elif norm_type.lower() == "hcurl0": M = inner(curl(v), curl(v)) * dx() else: cpp.dolfin_error( "norms.py", "compute norm", "Unknown norm type (\"%s\") for functions" % str(norm_type)) else: cpp.dolfin_error( "norms.py", "compute norm", "Unknown object type. Must be a vector or a function") # Get mesh if isinstance(v, Function) and mesh is None: mesh = v.function_space().mesh() # Assemble value r = assemble(M, mesh=mesh, form_compiler_parameters={"representation": "quadrature"}) # Check value if r < 0.0: cpp.dolfin_error( "norms.py", "compute norm", "Square of norm is negative, might be a round-off error") elif r == 0.0: return 0.0 else: return sqrt(r)
def norm(v, norm_type="L2", mesh=None): """ Return the norm of a given vector or function. *Arguments* v a :py:class:`Vector <dolfin.cpp.Vector>` or a :py:class:`Function <dolfin.functions.function.Function>`. norm_type see below for alternatives. mesh optional :py:class:`Mesh <dolfin.cpp.Mesh>` on which to compute the norm. If the norm type is not specified, the standard :math:`L^2` -norm is computed. Possible norm types include: *Vectors* ================ ================= ================ Norm Usage ================ ================= ================ :math:`l^2` norm(x, 'l2') Default :math:`l^1` norm(x, 'l1') :math:`l^\infty` norm(x, 'linf') ================ ================= ================ *Functions* ================ ================= ================================= Norm Usage Includes the :math:`L^2` -term ================ ================= ================================= :math:`L^2` norm(v, 'L2') Yes :math:`H^1` norm(v, 'H1') Yes :math:`H^1_0` norm(v, 'H10') No :math:`H` (div) norm(v, 'Hdiv') Yes :math:`H` (div) norm(v, 'Hdiv0') No :math:`H` (curl) norm(v, 'Hcurl') Yes :math:`H` (curl) norm(v, 'Hcurl0') No ================ ================= ================================= *Examples of usage* .. code-block:: python v = Function(V) x = v.vector() print norm(x, 'linf') # print the infinity norm of vector x n = norm(v) # compute L^2 norm of v print norm(v, 'Hdiv') # print H(div) norm of v n = norm(v, 'H1', mesh) # compute H^1 norm of v on given mesh """ if not isinstance(v, (GenericVector, GenericFunction)): raise TypeError, "expected a GenericVector or GenericFunction" # Check arguments if not isinstance(norm_type, str): cpp.dolfin_error("norms.py", "compute norm", "Norm type must be a string, not " + str(type(norm_type))) if mesh is not None and not isinstance(mesh, Mesh): cpp.dolfin_error("norms.py", "compute norm", "Expecting a Mesh, not " + str(type(mesh))) # Select norm type if isinstance(v, GenericVector): return v.norm(norm_type.lower()) elif (isinstance(v, Coefficient) and isinstance(v, GenericFunction)): if norm_type.lower() == "l2": M = inner(v, v)*dx() elif norm_type.lower() == "h1": M = inner(v, v)*dx() + inner(grad(v), grad(v))*dx() elif norm_type.lower() == "h10": M = inner(grad(v), grad(v))*dx() elif norm_type.lower() == "hdiv": M = inner(v, v)*dx() + div(v)*div(v)*dx() elif norm_type.lower() == "hdiv0": M = div(v)*div(v)*dx() elif norm_type.lower() == "hcurl": M = inner(v, v)*dx() + inner(curl(v), curl(v))*dx() elif norm_type.lower() == "hcurl0": M = inner(curl(v), curl(v))*dx() else: cpp.dolfin_error("norms.py", "compute norm", "Unknown norm type (\"%s\") for functions" % str(norm_type)) else: cpp.dolfin_error("norms.py", "compute norm", "Unknown object type. Must be a vector or a function") # Get mesh if isinstance(v, Function) and mesh is None: mesh = v.function_space().mesh() # Assemble value r = assemble(M, mesh=mesh, form_compiler_parameters={"representation": "quadrature"}) # Check value if r < 0.0: cpp.dolfin_error("norms.py", "compute norm", "Square of norm is negative, might be a round-off error") elif r == 0.0: return 0.0 else: return sqrt(r)
# Define variational problem F = rho*inner(a_*N_ddot(u) + b_*N_dot(u) + c_*u, w)*dx \ + inner(N_dot(S).T*Lambda_e + S.T*Lambda_p, grad(w))*dx \ - inner(g, w)*ds \ + inner(compliance(a_*N_ddot(S) + b_*N_dot(S) + c_*S), T)*dx \ - 0.5*inner(grad(u)*Lambda_p + Lambda_p*grad(u).T + grad(N_dot(u))*Lambda_e \ + Lambda_e*grad(N_dot(u)).T, T)*dx \ #- inner(f, w)*dx(1) \ a, L = lhs(F), rhs(F) # Assemble rhs (once) A = assemble(a) # Create GMRES Krylov solver solver = KrylovSolver(A, "gmres") # Create solution function S = Function(W) # Solving loop xdmf_file = XDMFFile(mesh.mpi_comm(), "output/elastodynamics.xdmf") if record: pvd = File("paraview/{}.pvd".format(file_name)) pvd << (u0, t)
] g = sum(pulses) F = rho * inner(a_ * N_ddot(u, u0, a0, v0, dt, beta) \ + b_ * N_dot(u, u0, v0, a0, dt, beta, gamma) + c_ * u, w) * dx \ + inner(N_dot(S, U0, V0, A0, dt, beta, gamma).T * Lambda_e + S.T * Lambda_p, grad(w)) * dx \ - inner(g, w) * ds \ + inner(compliance(a_ * N_ddot(S, U0, A0, V0, dt, beta) + b_ * N_dot(S, U0, V0, A0, dt, beta, gamma) + c_ * S, u, mu, lmbda), T) * dx \ - 0.5 * inner(grad(u) * Lambda_p + Lambda_p * grad(u).T + grad(N_dot(u, u0, v0, a0, dt, beta, gamma)) * Lambda_e \ + Lambda_e * grad(N_dot(u, u0, v0, a0, dt, beta, gamma)).T, T) * dx \ a, L = lhs(F), rhs(F) # Assemble rhs (once) A = assemble(a) # Create GMRES Krylov solver solver = KrylovSolver(A, "gmres") # Create solution function S = Function(W) experiment_count_file = open("experiment_counter", 'rb') experiment_count = pickle.load(experiment_count_file) experiment_count_file.close() paraview_file_name = "experiment_{}".format(experiment_count) info_file_name = "{}_experiments_info/info_n{}.txt".format( type_of_medium, experiment_count)
def forward(mu_expression, lmbda_expression, rho, Lx=10, Ly=10, t_end=1, omega_p=5, amplitude=5000, center=0, target=False): Lpml = Lx / 10 #c_p = cp(mu.vector(), lmbda.vector(), rho) max_velocity = 200 #c_p.max() stable_hx = stable_dx(max_velocity, omega_p) nx = int(Lx / stable_hx) + 1 #nx = max(nx, 60) ny = int(Ly * nx / Lx) + 1 mesh = mesh_generator(Lx, Ly, Lpml, nx, ny) used_hx = Lx / nx dt = stable_dt(used_hx, max_velocity) cfl_ct = cfl_constant(max_velocity, dt, used_hx) print(used_hx, stable_hx) print(cfl_ct) #time.sleep(10) PE = FunctionSpace(mesh, "DG", 0) mu = interpolate(mu_expression, PE) lmbda = interpolate(lmbda_expression, PE) m = 2 R = 10e-8 t = 0.0 gamma = 0.50 beta = 0.25 ff = MeshFunction("size_t", mesh, mesh.geometry().dim() - 1) Dirichlet(Lx, Ly, Lpml).mark(ff, 1) # Create function spaces VE = VectorElement("CG", mesh.ufl_cell(), 1, dim=2) TE = TensorElement("DG", mesh.ufl_cell(), 0, shape=(2, 2), symmetry=True) W = FunctionSpace(mesh, MixedElement([VE, TE])) F = FunctionSpace(mesh, "CG", 2) V = W.sub(0).collapse() M = W.sub(1).collapse() alpha_0 = Alpha_0(m, stable_hx, R, Lpml) alpha_1 = Alpha_1(alpha_0, Lx, Lpml, degree=2) alpha_2 = Alpha_2(alpha_0, Ly, Lpml, degree=2) beta_0 = Beta_0(m, max_velocity, R, Lpml) beta_1 = Beta_1(beta_0, Lx, Lpml, degree=2) beta_2 = Beta_2(beta_0, Ly, Lpml, degree=2) alpha_1 = interpolate(alpha_1, F) alpha_2 = interpolate(alpha_2, F) beta_1 = interpolate(beta_1, F) beta_2 = interpolate(beta_2, F) a_ = alpha_1 * alpha_2 b_ = alpha_1 * beta_2 + alpha_2 * beta_1 c_ = beta_1 * beta_2 Lambda_e = as_tensor([[alpha_2, 0], [0, alpha_1]]) Lambda_p = as_tensor([[beta_2, 0], [0, beta_1]]) a_ = alpha_1 * alpha_2 b_ = alpha_1 * beta_2 + alpha_2 * beta_1 c_ = beta_1 * beta_2 Lambda_e = as_tensor([[alpha_2, 0], [0, alpha_1]]) Lambda_p = as_tensor([[beta_2, 0], [0, beta_1]]) # Set up boundary condition bc = DirichletBC(W.sub(0), Constant(("0.0", "0.0")), ff, 1) # Create measure for the source term dx = Measure("dx", domain=mesh) ds = Measure("ds", domain=mesh, subdomain_data=ff) # Set up initial values u0 = Function(V) u0.set_allow_extrapolation(True) v0 = Function(V) a0 = Function(V) U0 = Function(M) V0 = Function(M) A0 = Function(M) # Test and trial functions (u, S) = TrialFunctions(W) (w, T) = TestFunctions(W) g = ModifiedRickerPulse(0, omega_p, amplitude, center) F = rho * inner(a_ * N_ddot(u, u0, a0, v0, dt, beta) \ + b_ * N_dot(u, u0, v0, a0, dt, beta, gamma) + c_ * u, w) * dx \ + inner(N_dot(S, U0, V0, A0, dt, beta, gamma).T * Lambda_e + S.T * Lambda_p, grad(w)) * dx \ - inner(g, w) * ds \ + inner(compliance(a_ * N_ddot(S, U0, A0, V0, dt, beta) + b_ * N_dot(S, U0, V0, A0, dt, beta, gamma) + c_ * S, u, mu, lmbda), T) * dx \ - 0.5 * inner(grad(u) * Lambda_p + Lambda_p * grad(u).T + grad(N_dot(u, u0, v0, a0, dt, beta, gamma)) * Lambda_e \ + Lambda_e * grad(N_dot(u, u0, v0, a0, dt, beta, gamma)).T, T) * dx \ a, L = lhs(F), rhs(F) # Assemble rhs (once) A = assemble(a) # Create GMRES Krylov solver solver = KrylovSolver(A, "gmres") # Create solution function S = Function(W) if target: xdmffile_u = XDMFFile("inversion_temporal_file/target/u.xdmf") pvd = File("inversion_temporal_file/target/u.pvd") xdmffile_u.write(u0, t) timeseries_u = TimeSeries( "inversion_temporal_file/target/u_timeseries") else: xdmffile_u = XDMFFile("inversion_temporal_file/obs/u.xdmf") xdmffile_u.write(u0, t) timeseries_u = TimeSeries("inversion_temporal_file/obs/u_timeseries") rec_counter = 0 while t < t_end - 0.5 * dt: t += float(dt) if rec_counter % 10 == 0: print( '\n\rtime: {:.3f} (Progress: {:.2f}%)'.format( t, 100 * t / t_end), ) g.t = t # Assemble rhs and apply boundary condition b = assemble(L) bc.apply(A, b) # Compute solution solver.solve(S.vector(), b) (u, U) = S.split(True) # Update previous time step update(u, u0, v0, a0, beta, gamma, dt) update(U, U0, V0, A0, beta, gamma, dt) xdmffile_u.write(u, t) pvd << (u, t) timeseries_u.store(u.vector(), t) energy = inner(u, u) * dx E = assemble(energy) print("E = ", E) print(u.vector().max())