def _change_degree(self, degree, *args, **kwargs): gc.collect() with self.global_preprocessing_time: logger.debug('Creating function space...') self._V = FunctionSpace(self._mesh, "CG", degree) logger.debug('Done. Creating integration subdomains...') self.create_integration_subdomains() logger.debug('Done. Creating test function...') self._v = TestFunction(self._V) logger.debug('Done. Creating potential function...') self._potential_function = Function(self._V) logger.debug('Done. Creating trial function...') self._potential_trial = TrialFunction(self._V) logger.debug('Done. Creating LHS part of equation...') self._a = self._lhs() logger.debug('Done. Assembling linear equation matrix...') self._terms_with_unknown = assemble(self._a) logger.debug('Done. Defining boundary condition...') self._dirichlet_bc = self._boundary_condition(*args, **kwargs) logger.debug('Done. Applying boundary condition to the matrix...') self._dirichlet_bc.apply(self._terms_with_unknown) logger.debug('Done. Creating solver...') self._solver = KrylovSolver("cg", "ilu") self._solver.parameters["maximum_iterations"] = self.MAX_ITER self._solver.parameters["absolute_tolerance"] = 1E-8 logger.debug('Done. Solver created.') self._degree = degree
def les_setup(u_, mesh, KineticEnergySGS, assemble_matrix, CG1Function, nut_krylov_solver, bcs, **NS_namespace): """ Set up for solving the Kinetic Energy SGS-model. """ DG = FunctionSpace(mesh, "DG", 0) CG1 = FunctionSpace(mesh, "CG", 1) dim = mesh.geometry().dim() delta = Function(DG) delta.vector().zero() delta.vector().axpy(1.0, assemble(TestFunction(DG) * dx)) delta.vector().set_local(delta.vector().array()**(1. / dim)) delta.vector().apply('insert') Ck = KineticEnergySGS["Ck"] ksgs = interpolate(Constant(1E-7), CG1) bc_ksgs = DirichletBC(CG1, 0, "on_boundary") A_mass = assemble_matrix(TrialFunction(CG1) * TestFunction(CG1) * dx) nut_form = Ck * delta * sqrt(ksgs) bcs_nut = derived_bcs(CG1, bcs['u0'], u_) nut_ = CG1Function(nut_form, mesh, method=nut_krylov_solver, bcs=bcs_nut, bounded=True, name="nut") At = Matrix() bt = Vector(nut_.vector()) ksgs_sol = KrylovSolver("bicgstab", "additive_schwarz") #ksgs_sol.parameters["preconditioner"]["structure"] = "same_nonzero_pattern" ksgs_sol.parameters["error_on_nonconvergence"] = False ksgs_sol.parameters["monitor_convergence"] = False ksgs_sol.parameters["report"] = False del NS_namespace return locals()
def solve_alpha_M_beta_F(self, alpha, beta, b, t): """Solve :code:`alpha * M * u + beta * F(u, t) = b` with Dirichlet conditions. """ matrix = alpha * self.M + beta * self.A # See above for float conversion right_hand_side = -float(beta) * self.b.copy() if b: right_hand_side += b for bc in self.dirichlet_bcs: bc.apply(matrix, right_hand_side) # TODO proper preconditioner for convection if self.convection: # Use HYPRE-Euclid instead of ILU for parallel computation. # However, this PC sometimes fails. # solver = KrylovSolver('gmres', 'hypre_euclid') # Fallback: solver = LUSolver() else: solver = KrylovSolver("gmres", "hypre_amg") solver.parameters["relative_tolerance"] = 1.0e-13 solver.parameters["absolute_tolerance"] = 0.0 solver.parameters["maximum_iterations"] = 100 solver.parameters["monitor_convergence"] = True solver.set_operator(matrix) u = Function(self.Q) solver.solve(u.vector(), right_hand_side) return u
def get_poisson_steps(pts, cells, tol): # Still can't initialize a mesh from points, cells filename = "mesh.xdmf" if cells.shape[1] == 3: meshio.write_points_cells(filename, pts, {"triangle": cells}) else: assert cells.shape[1] == 4 meshio.write_points_cells(filename, pts, {"tetra": cells}) mesh = Mesh() with XDMFFile(filename) as f: f.read(mesh) os.remove(filename) os.remove("mesh.h5") # build Laplace matrix with Dirichlet boundary using dolfin V = FunctionSpace(mesh, "Lagrange", 1) u = TrialFunction(V) v = TestFunction(V) a = inner(grad(u), grad(v)) * dx u0 = Constant(0.0) bc = DirichletBC(V, u0, "on_boundary") f = Constant(1.0) L = f * v * dx A = assemble(a) b = assemble(L) bc.apply(A, b) # solve(A, x, b, "cg") solver = KrylovSolver("cg", "none") solver.parameters["absolute_tolerance"] = 0.0 solver.parameters["relative_tolerance"] = tol x = Function(V) x_vec = x.vector() num_steps = solver.solve(A, x_vec, b) # # convert to scipy matrix # A = as_backend_type(A).mat() # ai, aj, av = A.getValuesCSR() # A = scipy.sparse.csr_matrix( # (av, aj, ai), shape=(A.getLocalSize()[0], A.getSize()[1]) # ) # # ev = eigvals(A.todense()) # ev_max = scipy.sparse.linalg.eigs(A, k=1, which="LM")[0][0] # assert numpy.abs(ev_max.imag) < 1.0e-15 # ev_max = ev_max.real # ev_min = scipy.sparse.linalg.eigs(A, k=1, which="SM")[0][0] # assert numpy.abs(ev_min.imag) < 1.0e-15 # ev_min = ev_min.real # cond = ev_max / ev_min # solve poisson system, count num steps # b = numpy.ones(A.shape[0]) # out = pykry.gmres(A, b) # num_steps = len(out.resnorms) return num_steps
def __init__(self): mesh = UnitSquareMesh(200, 200) self.V = FunctionSpace(mesh, 'Lagrange', 2) test, trial = TestFunction(self.V), TrialFunction(self.V) M = assemble(inner(test, trial) * dx) #self.M = assemble(inner(test, trial)*dx) self.solverM = KrylovSolver("cg", "amg") self.solverM.set_operator(M)
def solve_alpha_M_beta_F(self, alpha, beta, b, t): # Solve alpha * M * u + beta * F(u, t) = b for u. A = alpha * self.M + beta * self.A f.t = t v = TestFunction(self.V) b2 = assemble(f * v * dx) rhs = b.vector() - beta * b2 self.bcs.apply(A, rhs) solver = \ KrylovSolver('gmres', 'ilu') if alpha < 0.0 or beta > 0.0 \ else KrylovSolver('cg', 'amg') solver.parameters['relative_tolerance'] = 1.0e-13 solver.parameters['absolute_tolerance'] = 0.0 solver.parameters['maximum_iterations'] = 100 solver.parameters['monitor_convergence'] = False solver.set_operator(A) u = Function(self.V) solver.solve(u.vector(), rhs) return u
def __init__(self, fem, grounded_plate_at): self.GROUNDED_PLATE_AT = grounded_plate_at self.fem = fem self.CONDUCTIVITY = list(fem.CONDUCTIVITY) self.BOUNDARY_CONDUCTIVITY = list(fem.BOUNDARY_CONDUCTIVITY) self.solver = KrylovSolver("cg", "ilu") self.solver.parameters["maximum_iterations"] = 1000 self.solver.parameters["absolute_tolerance"] = 1E-8 self.V = fem._fm.function_space self.v = fem._fm.test_function() self.u = fem._fm.trial_function() self.dx = fem._dx self.ds = fem._ds
def solve_alpha_M_beta_F(self, alpha, beta, b, t): # Solve alpha * M * u + beta * F(u, t) = b for u. A = alpha * self.M + beta * self.A rhs = b - beta * self.b self.bcs.apply(A, rhs) solver = KrylovSolver('gmres', 'ilu') solver.parameters['relative_tolerance'] = 1.0e-13 solver.parameters['absolute_tolerance'] = 0.0 solver.parameters['maximum_iterations'] = 100 solver.parameters['monitor_convergence'] = True solver.set_operator(A) u = Function(self.V) solver.solve(u.vector(), rhs) return u
def before_first_compute(self, get): u = get("Velocity") assert len(u) == 2, "Can only compute stream function for 2D problems" V = u.function_space() spaces = SpacePool(V.mesh()) degree = V.ufl_element().degree() V = spaces.get_space(degree, 0) psi = TrialFunction(V) self.q = TestFunction(V) a = dot(grad(psi), grad(self.q)) * dx() self.bc = DirichletBC(V, Constant(0), DomainBoundary()) self.A = assemble(a) self.L = Vector() self.bc.apply(self.A) self.solver = KrylovSolver(self.A, "cg") self.psi = Function(V)
def main_slice_fem(mesh, subdomains, boundaries, src_pos, snk_pos): sigma_ROI = Constant(params.sigma_roi) sigma_SLICE = Constant(params.sigma_slice) sigma_SALINE = Constant(params.sigma_saline) sigma_AIR = Constant(0.) V = FunctionSpace(mesh, "CG", 2) v = TestFunction(V) u = TrialFunction(V) phi = Function(V) dx = Measure("dx")(subdomain_data=subdomains) ds = Measure("ds")(subdomain_data=boundaries) a = inner(sigma_ROI * grad(u), grad(v))*dx(params.roivol) + \ inner(sigma_SLICE * grad(u), grad(v))*dx(params.slicevol) + \ inner(sigma_SALINE * grad(u), grad(v))*dx(params.salinevol) L = Constant(0) * v * dx A = assemble(a) b = assemble(L) x_pos, y_pos, z_pos = src_pos point = Point(x_pos, y_pos, z_pos) delta = PointSource(V, point, 1.) delta.apply(b) x_pos, y_pos, z_pos = snk_pos point1 = Point(x_pos, y_pos, z_pos) delta1 = PointSource(V, point1, -1.) delta1.apply(b) solver = KrylovSolver("cg", "ilu") solver.parameters["maximum_iterations"] = 1000 solver.parameters["absolute_tolerance"] = 1E-8 solver.parameters["monitor_convergence"] = True info(solver.parameters, True) # set_log_level(PROGRESS) does not work in fenics 2018.1.0 solver.solve(A, phi.vector(), b) ele_pos_list = params.ele_coords vals = extract_pots(phi, ele_pos_list) # np.save(os.path.join('results', save_as), vals) return vals
def _set_degree(self, degree): self._fm.degree = degree with self.global_preprocessing_time: logger.debug('Creating integration subdomains...') self.create_integration_subdomains() logger.debug('Done. Creating test function...') self._v = self._fm.test_function() logger.debug('Done. Creating potential function...') self._potential_function = self._fm.function() logger.debug('Done. Creating trial function...') self._potential_trial = self._fm.trial_function() logger.debug('Done. Creating LHS part of equation...') self._a = self._lhs() logger.debug('Done. Creating base potential formula...') self._base_potential_expression = self._potential_expression() self._base_potential_gradient_normal_expression = self._potential_gradient_normal( ) logger.debug('Done. Creating solver...') self._solver = KrylovSolver("cg", "ilu") self._solver.parameters["maximum_iterations"] = self.MAX_ITER self._solver.parameters["absolute_tolerance"] = 1E-8 logger.debug('Done. Solver created.')
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) experiment_count += 1 experiment_count_file = open("experiment_counter", 'wb')
def solve(WP, bcs, mu, f, verbose=True, tol=1.0e-13, max_iter=500): # Some initial sanity checks. assert mu > 0.0 # Define variational problem (u, p) = TrialFunctions(WP) (v, q) = TestFunctions(WP) # Build system. # The sign of the div(u)-term is somewhat arbitrary since the right-hand # side is 0 here. We can either make the system symmetric or positive- # definite. # On a second note, we have # # \int grad(p).v = - \int p * div(v) + \int_\Gamma p n.v. # # Since, we have either p=0 or n.v=0 on the boundary, we could as well # replace the term dot(grad(p), v) by -p*div(v). # a = mu * inner(grad(u), grad(v))*dx \ - p * div(v) * dx \ - q * div(u) * dx # a = mu * inner(grad(u), grad(v))*dx + dot(grad(p), v) * dx \ # - div(u) * q * dx L = inner(f, v) * dx A, b = assemble_system(a, L, bcs) # Use the preconditioner as recommended in # <http://fenicsproject.org/documentation/dolfin/dev/python/demo/pde/stokes-iterative/python/documentation.html>, # # prec = inner(grad(u), grad(v))*dx - p*q*dx # # although it doesn't seem to be too efficient. # The sign on the last term doesn't matter. prec = mu * inner(grad(u), grad(v))*dx \ - p*q*dx M, _ = assemble_system(prec, L, bcs) # solver = KrylovSolver('tfqmr', 'hypre_amg') solver = KrylovSolver('gmres', 'hypre_amg') solver.set_operators(A, M) # For an assortment of preconditioners, see # # Performance and analysis of saddle point preconditioners # for the discrete steady-state Navier-Stokes equations; # H.C. Elman, D.J. Silvester, A.J. Wathen; # Numer. Math. (2002) 90: 665-688; # <http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.145.3554>. # # Set up field split. # <https://fenicsproject.org/qa/12856/fieldsplit-petscpreconditioner_set_fieldsplit-arguments> # PETScOptions.set('ksp_view') # PETScOptions.set('ksp_monitor_true_residual') # PETScOptions.set('pc_type', 'fieldsplit') # PETScOptions.set('pc_fieldsplit_type', 'additive') # PETScOptions.set('pc_fieldsplit_detect_saddle_point') # PETScOptions.set('fieldsplit_0_ksp_type', 'preonly') # PETScOptions.set('fieldsplit_0_pc_type', 'lu') # PETScOptions.set('fieldsplit_1_ksp_type', 'preonly') # PETScOptions.set('fieldsplit_1_pc_type', 'jacobi') # solver = PETScKrylovSolver('gmres') # solver.set_operator(A) # solver.set_from_options() # http://scicomp.stackexchange.com/questions/7288/which-preconditioners-and-solver-in-petsc-for-indefinite-symmetric-systems-sho # PETScOptions.set('pc_type', 'fieldsplit') # #PETScOptions.set('pc_fieldsplit_type', 'schur') # #PETScOptions.set('pc_fieldsplit_schur_fact_type', 'upper') # PETScOptions.set('pc_fieldsplit_detect_saddle_point') # #PETScOptions.set('fieldsplit_u_pc_type', 'lsc') # #PETScOptions.set('fieldsplit_u_ksp_type', 'preonly') # PETScOptions.set('pc_type', 'fieldsplit') # PETScOptions.set('fieldsplit_u_pc_type', 'hypre') # PETScOptions.set('fieldsplit_u_ksp_type', 'preonly') # PETScOptions.set('fieldsplit_p_pc_type', 'jacobi') # PETScOptions.set('fieldsplit_p_ksp_type', 'preonly') # # From PETSc/src/ksp/ksp/examples/tutorials/ex42-fsschur.opts: # PETScOptions.set('pc_type', 'fieldsplit') # PETScOptions.set('pc_fieldsplit_type', 'SCHUR') # PETScOptions.set('pc_fieldsplit_schur_fact_type', 'UPPER') # PETScOptions.set('fieldsplit_p_ksp_type', 'preonly') # PETScOptions.set('fieldsplit_u_pc_type', 'bjacobi') # From # # Composable Linear Solvers for Multiphysics; # J. Brown, M. Knepley, D.A. May, L.C. McInnes, B. Smith; # <http://www.computer.org/csdl/proceedings/ispdc/2012/4805/00/4805a055-abs.html>; # <http://www.mcs.anl.gov/uploads/cels/papers/P2017-0112.pdf>. # # PETScOptions.set('pc_type', 'fieldsplit') # PETScOptions.set('pc_fieldsplit_type', 'schur') # PETScOptions.set('pc_fieldsplit_schur_factorization_type', 'upper') # # # PETScOptions.set('fieldsplit_u_ksp_type', 'cg') # PETScOptions.set('fieldsplit_u_ksp_rtol', 1.0e-6) # PETScOptions.set('fieldsplit_u_pc_type', 'bjacobi') # PETScOptions.set('fieldsplit_u_sub_pc_type', 'cholesky') # # # PETScOptions.set('fieldsplit_p_ksp_type', 'fgmres') # PETScOptions.set('fieldsplit_p_ksp_constant_null_space') # PETScOptions.set('fieldsplit_p_pc_type', 'lsc') # # # PETScOptions.set('fieldsplit_p_lsc_ksp_type', 'cg') # PETScOptions.set('fieldsplit_p_lsc_ksp_rtol', 1.0e-2) # PETScOptions.set('fieldsplit_p_lsc_ksp_constant_null_space') # #PETScOptions.set('fieldsplit_p_lsc_ksp_converged_reason') # PETScOptions.set('fieldsplit_p_lsc_pc_type', 'bjacobi') # PETScOptions.set('fieldsplit_p_lsc_sub_pc_type', 'icc') solver.parameters['monitor_convergence'] = verbose solver.parameters['report'] = verbose solver.parameters['absolute_tolerance'] = 0.0 solver.parameters['relative_tolerance'] = tol solver.parameters['maximum_iterations'] = max_iter solver.parameters['error_on_nonconvergence'] = True # Solve up = Function(WP) solver.solve(up.vector(), b) # Get sub-functions u, p = up.split(True) return u, p
def solve( V, dx, Mu, Sigma, # dictionaries omega, f_list, # list of dictionaries convections, # dictionary f_degree=None, bcs=None, tol=1.0e-12, verbose=False, ): """Solve the complex-valued time-harmonic Maxwell system in 2D cylindrical coordinates .. math:: \\div\\left(\\frac{1}{\\mu r} \\nabla(r\\phi)\\right) + \\left\\langle u, \\frac{1}{r} \\nabla(r\\phi)\\right\\rangle + i \\sigma \\omega \\phi = f with finite elements. :param V: function space for potentials :param dx: measure :param Mu: mu per subdomain :type Mu: dictionary :param Sigma: sigma per subdomain :type Sigma: dictionary :param omega: current frequency :type omega: float :param f_list: list of right-hand sides for each of which a solution will be computed :param convections: convection, defined per subdomain :type convections: dictionary :param bcs: Dirichlet boundary conditions :param tol: relative solver tolerance :type tol: float :param verbose: solver verbosity :type verbose: boolean :rtype: list of functions """ # For the exact solution of the magnetic scalar potential, see # <http://www.physics.udel.edu/~jim/PHYS809_10F/Class_Notes/Class_26.pdf>. # Here, the value of \\phi along the rotational axis is specified as # # phi(z) = 2 pi I / c * (z/|z| - z/sqrt(z^2 + a^2)) # # where 'a' is the radius of the coil. This expression contradicts what is # specified by [Chaboudez97]_ who claim that phi=0 is the natural value # at the symmetry axis. # # For more analytic expressions, see # # Simple Analytic Expressions for the Magnetic Field of a Circular # Current Loop; # James Simpson, John Lane, Christopher Immer, and Robert Youngquist; # <http://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/20010038494_2001057024.pdf>. # # Check if boundary conditions on phi are explicitly provided. if not bcs: # Create Dirichlet boundary conditions. # In the cylindrically symmetric formulation, the magnetic vector # potential is given by # # A = e^{i omega t} phi(r,z) e_{theta}. # # It is natural to demand phi=0 along the symmetry axis r=0 to avoid # discontinuities there. # Also, this makes sure that the system is well-defined (see comment # below). # def xzero(x, on_boundary): return on_boundary and abs(x[0]) < DOLFIN_EPS ee = V.ufl_element() * V.ufl_element() VV = FunctionSpace(V.mesh(), ee) bcs = DirichletBC(VV, (0.0, 0.0), xzero) # # Concerning the boundary conditions for the rest of the system: # At the other boundaries, it is not uncommon (?) to set so-called # impedance boundary conditions; see, e.g., # # Chaboudez et al., # Numerical Modeling in Induction Heating for Axisymmetric # Geometries, # IEEE Transactions on Magnetics, vol. 33, no. 1, Jan 1997, # <http://www.esi-group.com/products/casting/publications/Articles_PDF/InductionaxiIEEE97.pdf>. # # or # # <ftp://ftp.math.ethz.ch/pub/sam-reports/reports/reports2010/2010-39.pdf>. # # TODO review those, references don't seem to be too accurate # Those translate into Robin-type boundary conditions (and are in fact # sometimes called that, cf. # https://en.wikipedia.org/wiki/Robin_boundary_condition). # The classical reference is # # Impedance boundary conditions for imperfectly conducting surfaces, # T.B.A. Senior, # <http://link.springer.com/content/pdf/10.1007/BF02920074>. # # class OuterBoundary(SubDomain): # def inside(self, x, on_boundary): # return on_boundary and abs(x[0]) > DOLFIN_EPS # boundaries = MeshFunction( # 'size_t', mesh, # mesh.topology().dim() - 1 # ) # boundaries.set_all(0) # outer_boundary = OuterBoundary() # outer_boundary.mark(boundaries, 1) # ds = Measure('ds')[boundaries] # #n = FacetNormal(mesh) # #a += - 1.0/Mu[i] * dot(grad(r*ur), n) * vr * ds(1) \ # # - 1.0/Mu[i] * dot(grad(r*ui), n) * vi * ds(1) # #L += - 1.0/Mu[i] * 1.0 * vr * ds(1) \ # # - 1.0/Mu[i] * 1.0 * vi * ds(1) # # This is -n.grad(r u) = u: # a += 1.0/Mu[i] * ur * vr * ds(1) \ # + 1.0/Mu[i] * ui * vi * ds(1) # Create the system matrix, preconditioner, and the right-hand sides. # For preconditioners, there are two approaches. The first one, described # in # # Algebraic Multigrid for Complex Symmetric Systems; # D. Lahaye, H. De Gersem, S. Vandewalle, and K. Hameyer; # <https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=877730> # # doesn't work too well here. # The matrix P, created in build_system(), provides a better alternative. # For more details, see documentation in build_system(). # A, P, b_list, _, W = build_system(V, dx, Mu, Sigma, omega, f_list, f_degree, convections, bcs) # prepare solver # Don't use 'amg', since that defaults to `ml_amg` if available which # crashes # <https://bitbucket.org/fenics-project/docker/issues/61/petsc-vectorfunctionspace-amg-malloc>. solver = KrylovSolver("gmres", "hypre_amg") solver.set_operators(A, P) # The PDE for A has huge coefficients (order 10^8) all over. Hence, if # relative residual is set to 10^-6, the actual residual will still be of # the order 10^2. While this isn't too bad (after all the equations are # upscaled by a large factor), one can choose a very small relative # tolerance here to get a visually pleasing residual norm. solver.parameters["relative_tolerance"] = tol solver.parameters["absolute_tolerance"] = 0.0 solver.parameters["maximum_iterations"] = 100 solver.parameters["report"] = verbose solver.parameters["monitor_convergence"] = verbose phi_list = [] for k, b in enumerate(b_list): phi_list.append(Function(W)) phi_list[-1].rename("phi{}".format(k), "phi{}".format(k)) solver.solve(phi_list[-1].vector(), b) return phi_list
def before_first_compute(self, get): u = get(self.valuename) if isinstance(u, Function): if LooseVersion(dolfin_version()) > LooseVersion("1.6.0"): rank = len(u.ufl_shape) else: rank = u.rank() if rank == 0: self.f = Function(u.function_space()) elif rank >= 1: # Assume all subpaces are equal V = u.function_space().extract_sub_space([0]).collapse() mesh = V.mesh() el = V.ufl_element() self.f = Function(V) # Find out if we can operate directly on vectors, or if we have to use a projection # We can operate on vectors if all sub-dofmaps are ordered the same way # For simplicity, this is only tested for CG- or DG0-spaces # (this might always be true for these spaces, but better to be safe than sorry ) self.use_project = True if el.family() == "Lagrange" or (el.family() == "Discontinuous Lagrange" and el.degree() == 0): #dm = u.function_space().dofmap() dm0 = V.dofmap() self.use_project = False for i in xrange(u.function_space().num_sub_spaces()): Vi = u.function_space().extract_sub_space( [i]).collapse() dmi = Vi.dofmap() try: # For 1.6.0+ and newer diff = Vi.tabulate_dof_coordinates( ) - V.tabulate_dof_coordinates() except: # For 1.6.0 and older diff = dmi.tabulate_all_coordinates( mesh) - dm0.tabulate_all_coordinates(mesh) if len(diff) > 0: max_diff = max(abs(diff)) else: max_diff = 0.0 max_diff = MPI.max(mpi_comm_world(), max_diff) if max_diff > 1e-12: self.use_project = True break self.assigner = FunctionAssigner( [V] * u.function_space().num_sub_spaces(), u.function_space()) self.subfuncs = [ Function(V) for _ in range(u.function_space().num_sub_spaces()) ] # IF we have to use a projection, build projection matrix only once if self.use_project: self.v = TestFunction(V) M = assemble(inner(self.v, TrialFunction(V)) * dx) self.projection = KrylovSolver("cg", "default") self.projection.set_operator(M) elif isinstance(u, Iterable) and all( isinstance(_u, Number) for _u in u): pass elif isinstance(u, Number): pass else: # Don't know how to handle object cbc_warning( "Don't know how to calculate magnitude of object of type %s." % type(u))
source_z=7.85, source_y=0, sigma_2=0.1, A=(2 * np.pi * 0.1) ** -1.5, degree=DEGREE) #B_inv = assemble(csd * Measure('dx', mesh)) # csd_at = interpolate(csd, V) # csd_at(0, 0, 7.2) < 0 def boundary(x, on_boundary): return x[1] <= NECK_AT bc = DirichletBC(V, Constant(0.), boundary) solver = KrylovSolver("cg", "ilu") solver.parameters["maximum_iterations"] = 1100 solver.parameters["absolute_tolerance"] = 1E-8 #solver.parameters["monitor_convergence"] = True SOURCES = [] DBG = {} TMP_FILENAME = f'proof_of_concept_fem_dirchlet_newman_CTX_deg_{DEGREE}_.npz' try: fh = np.load(TMP_FILENAME) except FileNotFoundError: print('no previous results found') previously_solved = set()
def __call__(self, degree=3, y=0., standard_deviation=1.): V = FunctionSpace(self._mesh, "CG", degree) v = TestFunction(V) potential_trial = TrialFunction(V) potential = Function(V) dx = Measure("dx")(subdomain_data=self._subdomains) # ds = Measure("ds")(subdomain_data=self._boundaries) csd = Expression(f''' x[1] >= {self.H} ? 0 : a * exp({-0.5 / standard_deviation ** 2} * ((x[0])*(x[0]) + (x[1] - {y})*(x[1] - {y}) + (x[2])*(x[2]) )) ''', degree=degree, a=1.0) self.a = csd.a = 1.0 / assemble( csd * Measure("dx", self._mesh)) # print(assemble(csd * Measure("dx", self._mesh))) L = csd * v * dx known_terms = assemble(L) # a = (inner(grad(potential_trial), grad(v)) # * (Constant(self.SALINE_CONDUCTIVITY) * dx(self.SALINE_VOL) # + Constant(self.SLICE_CONDUCTIVITY) * (dx(self.SLICE_VOL) # + dx(self.ROI_VOL)))) a = sum( Constant(conductivity) * inner(grad(potential_trial), grad(v)) * dx(domain) for domain, conductivity in [ (self.SALINE_VOL, self.SALINE_CONDUCTIVITY), (self.SLICE_VOL, self.SLICE_CONDUCTIVITY), (self.ROI_VOL, self.SLICE_CONDUCTIVITY), ]) terms_with_unknown = assemble(a) dirchlet_bc = DirichletBC( V, Constant(2.0 * 0.25 / (self.RADIUS * np.pi * self.SALINE_CONDUCTIVITY)), # 2.0 becaue of dielectric base duplicating # the current source # slice conductivity and thickness considered # negligible self._boundaries, self.MODEL_DOME) dirchlet_bc.apply(terms_with_unknown, known_terms) solver = KrylovSolver("cg", "ilu") solver.parameters["maximum_iterations"] = MAX_ITER solver.parameters["absolute_tolerance"] = 1E-8 # solver.parameters["monitor_convergence"] = True start = datetime.datetime.now() try: self.iterations = solver.solve(terms_with_unknown, potential.vector(), known_terms) return potential except RuntimeError as e: self.iterations = MAX_ITER logger.warning("Solver failed: {}".format(repr(e))) return None finally: self.time = datetime.datetime.now() - start
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())