def test_compile_extension_module(): # This test should do basically the same as the docstring of the # compile_extension_module function in compilemodule.py. Remember # to update the docstring if the test is modified! code = """ #include <pybind11/pybind11.h> #include <petscvec.h> #include <dolfin/la/PETScVector.h> void PETSc_exp(Vec x) { assert(x); VecExp(x); } PYBIND11_MODULE(SIGNATURE, m) { m.def("PETSc_exp", &PETSc_exp); } """ ext_module = compile_cpp_code(code) local_range = MPI.local_range(MPI.comm_world, 10) x = cpp.la.create_vector(MPI.comm_world, local_range, [], 1) x_np = np.arange(float(local_range[1] - local_range[0])) with x.localForm() as lf: lf[:] = x_np ext_module.PETSc_exp(x) x_np = np.exp(x_np) x = x.getArray() assert (x == x_np).all()
def test_mpi_pybind11(): """ Test MPICommWrapper <-> mpi4py.MPI.Comm conversion for JIT-ed code """ cpp_code = """ #include <pybind11/pybind11.h> #include <dolfin_wrappers/MPICommWrapper.h> namespace dolfin { dolfin_wrappers::MPICommWrapper test_comm_passing(const dolfin_wrappers::MPICommWrapper comm) { MPI_Comm c = comm.get(); return dolfin_wrappers::MPICommWrapper(c); } } PYBIND11_MODULE(SIGNATURE, m) { m.def("test_comm_passing", &dolfin::test_comm_passing); } """ # Import MPI_COMM_WORLD from mpi4py import MPI w1 = MPI.COMM_WORLD # Compile the JIT module return pytest.xfail('Include path for dolfin_wrappers/* not set up to ' 'work in the JIT at the moment') mod = dolfin.compile_cpp_code(cpp_code) # Pass a comm into C++ and get a new wrapper of the same comm back w2 = mod.test_comm_passing(w1) assert isinstance(w2, MPI.Comm)
def _get_cpp_module(cpp_files, force_recompile=False): """ Use the dolfin machinery to compile, wrap with swig and load a c++ module """ cpp_dir = os.path.dirname(os.path.abspath(__file__)) cpp_sources = [] for cpp_filename in cpp_files: lines = [] for line in open(os.path.join(cpp_dir, cpp_filename), 'rt'): if line.startswith('#include') and 'remove_in_jit' in line: pass else: lines.append(line) cpp_sources.append(''.join(lines)) # Force recompilation if force_recompile: cpp_sources.append('// Force recompile, time is %s \n' % time.time()) sep = '\n\n// ' + '$' * 77 + '\n\n' cpp_code = sep.join(cpp_sources) module = compile_cpp_code(cpp_code) assert module is not None return module
def get_eigenvector(self, i): assert i < self.eigen_solver.get_number_converged() # Initialize eigenvectors real_vector = PETScVector() imag_vector = PETScVector() self.A.init_vector(real_vector, 0) self.A.init_vector(imag_vector, 0) # Condense input vectors if hasattr(self, "_is"): # there were Dirichlet BCs condensed_real_vector = PETScVector(real_vector.vec().getSubVector( self._is)) condensed_imag_vector = PETScVector(imag_vector.vec().getSubVector( self._is)) else: condensed_real_vector = real_vector condensed_imag_vector = imag_vector # Get eigenpairs if dolfin_version.startswith( "2018.1"): # TODO remove when 2018.2.0 is released # Helper functions cpp_code = """ #include <pybind11/pybind11.h> #include <dolfin/la/PETScVector.h> #include <dolfin/la/SLEPcEigenSolver.h> void get_eigen_pair(std::shared_ptr<dolfin::SLEPcEigenSolver> eigen_solver, std::shared_ptr<dolfin::PETScVector> condensed_real_vector, std::shared_ptr<dolfin::PETScVector> condensed_imag_vector, std::size_t i) { const PetscInt ii = static_cast<PetscInt>(i); double real_value; double imag_value; EPSGetEigenpair(eigen_solver->eps(), ii, &real_value, &imag_value, condensed_real_vector->vec(), condensed_imag_vector->vec()); } PYBIND11_MODULE(SIGNATURE, m) { m.def("get_eigen_pair", &get_eigen_pair); } """ get_eigen_pair = compile_cpp_code(cpp_code).get_eigen_pair get_eigen_pair(self.eigen_solver, condensed_real_vector, condensed_imag_vector, i) else: self.eigen_solver.get_eigenpair(condensed_real_vector, condensed_imag_vector, i) # Restore input vectors if hasattr(self, "_is"): # there were Dirichlet BCs real_vector.vec().restoreSubVector(self._is, condensed_real_vector.vec()) imag_vector.vec().restoreSubVector(self._is, condensed_imag_vector.vec()) # Return as Function return (Function(self.V, real_vector), Function(self.V, imag_vector))
def set_parameters(self, parameters): # Helper functions cpp_code = """ #include <pybind11/pybind11.h> #include <dolfin/la/PETScLUSolver.h> // defines PCFactorSetMatSolverType macro for PETSc <= 3.8 #include <dolfin/la/SLEPcEigenSolver.h> void throw_error(PetscErrorCode ierr, std::string reason); void set_linear_solver(std::shared_ptr<dolfin::SLEPcEigenSolver> eigen_solver, std::string lu_method) { ST st; KSP ksp; PC pc; PetscErrorCode ierr; ierr = EPSGetST(eigen_solver->eps(), &st); if (ierr != 0) throw_error(ierr, "EPSGetST"); ierr = STGetKSP(st, &ksp); if (ierr != 0) throw_error(ierr, "STGetKSP"); ierr = KSPGetPC(ksp, &pc); if (ierr != 0) throw_error(ierr, "KSPGetPC"); ierr = STSetType(st, STSINVERT); if (ierr != 0) throw_error(ierr, "STSetType"); ierr = KSPSetType(ksp, KSPPREONLY); if (ierr != 0) throw_error(ierr, "KSPSetType"); ierr = PCSetType(pc, PCLU); if (ierr != 0) throw_error(ierr, "PCSetType"); ierr = PCFactorSetMatSolverType(pc, lu_method.c_str()); if (ierr != 0) throw_error(ierr, "PCFactorSetMatSolverType"); } void throw_error(PetscErrorCode ierr, std::string reason) { throw std::runtime_error("Error in set_linear_solver: reason " + reason + ",error code " + std::to_string(ierr)); } PYBIND11_MODULE(SIGNATURE, m) { m.def("set_linear_solver", &set_linear_solver); } """ cpp_module = compile_cpp_code(cpp_code) set_linear_solver = cpp_module.set_linear_solver if "spectral_transform" in parameters and parameters[ "spectral_transform"] == "shift-and-invert": parameters["spectrum"] = "target real" if "linear_solver" in parameters: set_linear_solver(self.eigen_solver, parameters["linear_solver"]) parameters.pop("linear_solver") self.eigen_solver.parameters.update(parameters)
def _get_local_dof_to_component_map(V, component=None, dof_component_map=None, recursive=False): if component is None: component = [-1] if dof_component_map is None: dof_component_map = dict() # From dolfin/function/LagrangeInterpolator.cpp, # method LagrangeInterpolator::extract_dof_component_map # Copyright (C) 2014 Mikael Mortensen if V.num_sub_spaces() == 0: # Extract sub dofmaps recursively and store dof to component map if has_pybind11(): cpp_code = """ #include <pybind11/pybind11.h> #include <pybind11/stl.h> #include <dolfin/fem/DofMap.h> #include <dolfin/mesh/Mesh.h> std::vector<std::size_t> collapse_dofmap(std::shared_ptr<dolfin::DofMap> dofmap, std::shared_ptr<dolfin::Mesh> mesh) { std::unordered_map<std::size_t, std::size_t> collapsed_map; dofmap->collapse(collapsed_map, *mesh); std::vector<std::size_t> collapsed_dofs; collapsed_dofs.reserve(collapsed_map.size()); for (auto const& collapsed_map_item: collapsed_map) collapsed_dofs.push_back(collapsed_map_item.second); return collapsed_dofs; } PYBIND11_MODULE(SIGNATURE, m) { m.def("collapse_dofmap", &collapse_dofmap); } """ collapse_dofmap = compile_cpp_code(cpp_code).collapse_dofmap collapsed_dofs = collapse_dofmap(V.dofmap(), V.mesh()) else: collapsed_dofs = V.dofmap().collapse(V.mesh())[1].values() component[0] += 1 for collapsed_dof in collapsed_dofs: if not recursive: # space with only one component, do not print it dof_component_map[collapsed_dof] = -1 else: dof_component_map[collapsed_dof] = component[0] else: for i in range(V.num_sub_spaces()): Vs = V.sub(i) _get_local_dof_to_component_map(Vs, component, dof_component_map, True) if not recursive: return dof_component_map else: return None
def __init__(self, V, bnd, objects, vsources=None, isources=None, dt=None, int_bnd_ids=None, eps0=1): num_objects = len(objects) if int_bnd_ids == None: int_bnd_ids = [ objects[i].domain_args[1] for i in range(num_objects) ] if vsources == None: vsources = [] if isources == None: isources = [] self.dt = 1 else: assert dt != None self.dt = dt self.int_bnd_ids = int_bnd_ids self.vsources = vsources self.isources = isources self.objects = objects self.eps0 = eps0 self.groups = get_charge_sharing_sets(vsources, num_objects) self.V = V mesh = V.mesh() R = df.FunctionSpace(mesh, "Real", 0) self.mu = df.TestFunction(R) self.phi = df.TrialFunction(V) self.dss = df.Measure("ds", domain=mesh, subdomain_data=bnd) self.n = df.FacetNormal(mesh) thisdir = os.path.dirname(__file__) path = os.path.join(thisdir, 'addrow.cpp') code = open(path, 'r').read() self.compiled = df.compile_cpp_code(code) # Rows in which to store charge and potential constraints rows_charge = [g[0] for g in self.groups] rows_potential = list(set(range(num_objects)) - set(rows_charge)) self.rows_charge = [objects[i].get_free_row() for i in rows_charge] self.rows_potential = [ objects[i].get_free_row() for i in rows_potential ]
def compile_extension_module(cpp_code, **kwargs): if DOLFIN_VERSION_MAJOR >= 2018: headers = kwargs.get('additional_system_headers', []) headers = ["#include <Eigen/Core>", '#include <pybind11/pybind11.h>', # "using Array = Eigen::Ref<const Eigen::ArrayXi>;;"] +\ "using Array = Eigen::ArrayXi;"] +\ ['#include <' + h + '>' for h in headers if h != ''] cpp_code = '\n'.join(headers) + cpp_code return dolfin.compile_cpp_code(cpp_code) else: return dolfin.compile_extension_module(cpp_code, **kwargs)
def test_slepc(): create_eps_code = r''' #include <pybind11/pybind11.h> #include <dolfin.h> #include <slepc.h> namespace dolfin { std::shared_ptr<EPS> create_matrix(MPI_Comm comm) { EPS eps; EPSCreate(comm, &eps); std::shared_ptr<EPS> ptr = std::make_shared<EPS>(eps); return ptr; } } PYBIND11_MODULE(SIGNATURE, m) { m.def("create_matrix", &dolfin::create_matrix); } ''' compile_cpp_code(create_eps_code)
def compile_extension_module(cpp_code, **kwargs): if DOLFIN_VERSION_MAJOR >= 2018: headers = kwargs.get("additional_system_headers", []) headers = [ "#include <Eigen/Core>", "#include <pybind11/pybind11.h>", # "using Array = Eigen::Ref<const Eigen::ArrayXi>;;"] +\ "using Array = Eigen::ArrayXi;", ] + ["#include <" + h + ">" for h in headers if h != ""] cpp_code = "\n".join(headers) + cpp_code return dolfin.compile_cpp_code(cpp_code) else: return dolfin.compile_extension_module(cpp_code, **kwargs)
def CellCircumcenter(mesh, codes=codes): '''Circumcenter of cells in mesh''' assert mesh.ufl_cell().cellname() in ('interval', 'triangle', 'tetrahedron') gdim = mesh.geometry().dim() tdim = mesh.topology().dim() f = CompiledExpression(getattr(compile_cpp_code(codes[(tdim, gdim)]), f'Circumcenter_{tdim}_{gdim}')(), degree=0, mesh=mesh) V = df.VectorFunctionSpace(mesh, 'DG', 0) return df.interpolate(f, V)
def __init__(self, *args, **kwargs): # Adds the missing argument (the value on the boundary) before calling # the parent constructor. The value must be zero to set the # corresponding elements in the load vector to zero. args = list(args) args.insert(1, df.Constant(0.0)) self.monitor = False self.compiled_apply = kwargs.pop('compiled_apply', True) if self.compiled_apply: thisdir = os.path.dirname(__file__) path = os.path.join(thisdir, 'apply.cpp') code = open(path, 'r').read() self.compiled_apply = df.compile_cpp_code(code) df.DirichletBC.__init__(self, *args, **kwargs)
def build_distributed_mesh(mesh): """ Work around some missing dolfin pybind11 wrapped methods Performs the same actions as what happens when reading a mesh from an XML file, except for the very first step (constructing the whole global mesh on the root process) which is assumed to have happened allready """ if build_distributed_mesh.func is None: cpp_code = """ #include <pybind11/pybind11.h> #include <dolfin/common/MPI.h> #include <dolfin/mesh/MeshPartitioning.h> #include <dolfin/mesh/LocalMeshData.h> #include <dolfin/mesh/Mesh.h> #include <dolfin/parameter/GlobalParameters.h> /** Code taken from XMLFile::read(Mesh& input_mesh) in dolfin/io/XMLFile.cpp on 2018-03-21 */ void distribute_mesh(dolfin::Mesh &mesh) { // Distribute local data mesh.domains().clear(); dolfin::LocalMeshData local_mesh_data(mesh); // Mesh domain data not present if (dolfin::MPI::rank(mesh.mpi_comm()) == 0) local_mesh_data.domain_data.clear(); // Partition and build mesh const std::string ghost_mode = dolfin::parameters["ghost_mode"]; dolfin::MeshPartitioning::build_distributed_mesh(mesh, local_mesh_data, ghost_mode); } namespace py = pybind11; PYBIND11_MODULE(SIGNATURE, m) { m.def("distribute_mesh", &distribute_mesh, py::arg("mesh")); } """ build_distributed_mesh.func = dolfin.compile_cpp_code( cpp_code).distribute_mesh return build_distributed_mesh.func(mesh)
def _is_zero(form_or_block_form): assert ( isinstance(form_or_block_form, (array, cpp_Form, Form, list)) or (isinstance(form_or_block_form, (float, int)) and form_or_block_form in zeros) ) if isinstance(form_or_block_form, Form): return form_or_block_form.empty() elif isinstance(form_or_block_form, cpp_Form): _is_zero_form_cpp_code = """ #include <dolfin/fem/Form.h> #include <pybind11/pybind11.h> bool is_zero_form(std::shared_ptr<dolfin::Form> form) { return !form->ufc_form(); } PYBIND11_MODULE(SIGNATURE, m) { m.def("is_zero_form", &is_zero_form); } """ is_zero_form = compile_cpp_code(_is_zero_form_cpp_code).is_zero_form return is_zero_form(form_or_block_form) elif isinstance(form_or_block_form, (array, list)): block_form_rank = _get_block_form_rank(form_or_block_form) assert block_form_rank in (None, 1, 2) if block_form_rank == 2: for block_form_I in form_or_block_form: for block_form_IJ in block_form_I: if not _is_zero(block_form_IJ): return False return True elif block_form_rank == 1: for block_form_I in form_or_block_form: if not _is_zero(block_form_I): return False return True elif block_form_rank is None: return True elif isinstance(form_or_block_form, (float, int)) and form_or_block_form in zeros: return True else: raise AssertionError("Invalid case in _is_zero")
def test_pass_array_int(): code = """ #include <Eigen/Core> #include <pybind11/pybind11.h> #include <pybind11/eigen.h> using IntVecIn = Eigen::Ref<const Eigen::VectorXi>; int test_int_array(const IntVecIn arr) { return arr.sum(); } PYBIND11_MODULE(SIGNATURE, m) { m.def("test_int_array", &test_int_array); } """ module = compile_cpp_code(code) arr = np.array([1, 2, 4, 8], dtype=np.intc) ans = module.test_int_array(arr) assert ans == arr.sum() == 15
def test_mpi_pybind11(): """ Test MPICommWrapper <-> mpi4py.MPI.Comm conversion for JIT-ed code """ cpp_code = """ #include <pybind11/pybind11.h> #include <dolfin_wrappers/MPICommWrapper.h> namespace dolfin { dolfin_wrappers::MPICommWrapper test_comm_passing(const dolfin_wrappers::MPICommWrapper comm) { MPI_Comm c = comm.get(); return dolfin_wrappers::MPICommWrapper(c); } } PYBIND11_MODULE(SIGNATURE, m) { m.def("test_comm_passing", &dolfin::test_comm_passing); } """ # Import MPI_COMM_WORLD if dolfin.has_mpi4py(): from mpi4py import MPI w1 = MPI.COMM_WORLD else: w1 = dolfin.MPI.comm_world # Compile the JIT module return pytest.xfail('Include path for dolfin_wrappers/* not set up to ' 'work in the JIT at the moment') mod = dolfin.compile_cpp_code(cpp_code) # Pass a comm into C++ and get a new wrapper of the same comm back w2 = mod.test_comm_passing(w1) if dolfin.has_mpi4py(): assert isinstance(w2, MPI.Comm) else: assert isinstance(w2, dolfin.cpp.MPICommWrapper) assert w1.underlying_comm() == w2.underlying_comm()
def test_pass_array_double(): code = """ #include <Eigen/Core> #include <pybind11/pybind11.h> #include <pybind11/eigen.h> using DoubleVecIn = Eigen::Ref<const Eigen::VectorXd>; int test_double_array(const DoubleVecIn arr) { return arr.sum(); } PYBIND11_MODULE(SIGNATURE, m) { m.def("test_double_array", &test_double_array); } """ module = compile_cpp_code(code) arr = np.array([1, 2, 4, 8], dtype=float) ans = module.test_double_array(arr) assert abs(arr.sum() - 15) < 1e-15 assert abs(ans - 15) < 1e-15
def test_petsc(): create_matrix_code = r''' #include <pybind11/pybind11.h> #include <dolfin.h> namespace dolfin { std::shared_ptr<la::PETScMatrix> create_matrix(void) { Mat I; std::shared_ptr<la::PETScMatrix> ptr = std::make_shared<la::PETScMatrix>(I); return ptr; } } PYBIND11_MODULE(SIGNATURE, m) { m.def("create_matrix", &dolfin::create_matrix); } ''' module = compile_cpp_code(create_matrix_code) assert (module)
def test_petsc(): create_matrix_code = r''' #include <pybind11/pybind11.h> #include <dolfin.h> namespace dolfin { la::PETScMatrix create_matrix(void) { Mat I; la::PETScMatrix A = la::PETScMatrix(I); return A; } } PYBIND11_MODULE(SIGNATURE, m) { m.def("create_matrix", &dolfin::create_matrix); } ''' module = compile_cpp_code(create_matrix_code) assert (module)
def cpp_module( header_names: Sequence[str], include_dir: str = "include", verbose: bool = False ) -> "class <'module'>": include_path = Path(__file__).parent.resolve() / include_dir header_list = [] for header in header_names: with open(include_path / header, "r") as header_handle: header_list.append(header_handle.read()) separator = "\n"*4 cpp_code = separator.join(header_list) if verbose: print(cpp_code) module = compile_cpp_code( cpp_code, include_dirs=[] ) assert module is not None return module
def test_compile_extension_module(): # This test should do basically the same as the docstring of the # compile_extension_module function in compilemodule.py. Remember # to update the docstring if the test is modified! from numpy import arange, exp code = """ #include <pybind11/pybind11.h> #include <petscvec.h> #include <dolfin/la/PETScVector.h> void PETSc_exp(std::shared_ptr<dolfin::la::PETScVector> vec) { Vec x = vec->vec(); assert(x); VecExp(x); } PYBIND11_MODULE(SIGNATURE, m) { m.def("PETSc_exp", &PETSc_exp); } """ ext_module = compile_cpp_code(code) local_range = MPI.local_range(MPI.comm_world, 10) vec = PETScVector(MPI.comm_world, local_range, [], 1) np_vec = vec.get_local() np_vec[:] = arange(len(np_vec)) vec[:] = np_vec ext_module.PETSc_exp(vec) np_vec[:] = exp(np_vec) assert (np_vec == vec.get_local()).all()
def __init__(self): cpp_link_code = """ #include <hdf5.h> // dolfin headers #include <dolfin/io/HDF5Interface.h> #include <dolfin/common/MPI.h> // pybind headers #include <pybind11/pybind11.h> namespace py = pybind11; namespace dolfin { void link_dataset(const MPI_Comm comm, const std::string hdf5_filename, const std::string link_from, const std::string link_to, bool use_mpiio) { hid_t hdf5_file_id = HDF5Interface::open_file(comm, hdf5_filename, "a", use_mpiio); herr_t status = H5Lcreate_hard(hdf5_file_id, link_from.c_str(), H5L_SAME_LOC, link_to.c_str(), H5P_DEFAULT, H5P_DEFAULT); dolfin_assert(status != HDF5_FAIL); HDF5Interface::close_file(hdf5_file_id); } PYBIND11_MODULE(SIGNATURE, m) { m.def("link_dataset", &link_dataset); } } // end namespace dolfin """ # self.cpp_link_module = dolfin.compile_cpp_code(cpp_link_code, additional_system_headers=["dolfin/io/HDF5Interface.h"]) self.cpp_link_module = dolfin.compile_cpp_code(cpp_link_code)
def test_compile_extension_module_kwargs(): # This test check that instant_kwargs of compile_extension_module # are taken into account when computing signature m2 = compile_cpp_code('', cppargs='-O2') m0 = compile_cpp_code('', cppargs='') assert not m2.__file__ == m0.__file__
} namespace py = pybind11; PYBIND11_MODULE(SIGNATURE, m){ m.def("restrict", [](py::object v, const dolfin::FiniteElement& element, const dolfin::Cell& cell){ auto _v = v.attr("_cpp_object").cast<dolfin::Function&>(); std::vector<double> _w(element.space_dimension()); restrict(_v, element, cell, _w); return _w; }); } """ compiled = df.compile_cpp_code(code) restrict = compiled.restrict class Particle: __slots__ = ['position', 'properties'] 'Lagrangian particle with position and some other passive properties.' def __init__(self, x): self.position = x self.properties = {} def send(self, dest): 'Send particle to dest.' comm.Send(self.position, dest=dest) comm.send(self.properties, dest=dest) def recv(self, source):
m.def("dofmap_dofs_is", &dofmap_dofs_is); } namespace pybind11 { namespace detail { PETSC_CASTER_MACRO(IS, is); } } """ # Load and wrap compiled function dofmap_dofs_is path = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__))) module_dofs = compile_cpp_code(dofmap_dofs_is_cpp_code, include_dirs=[path, petsc4py.get_include()]) def dofmap_dofs_is(dofmap): """Converts DofMap::dofs() to IS. This function is intended to circumvent NumPy which would be involved in code like:: iset = PETSc.IS().createGeneral(dofmap.dofs(), comm=dofmap.index_map().mpi_comm()) """ iset = module_dofs.dofmap_dofs_is(dofmap) iset.decRef() assert iset.getRefCount() == 1
def from_parameters(cls, params=None): params = params or {} parameters = cls.default_parameters() parameters.update(params) msh_name = Path("test.msh") create_benchmark_ellipsoid_mesh_gmsh( msh_name, r_short_endo=parameters["r_short_endo"], r_short_epi=parameters["r_short_epi"], r_long_endo=parameters["r_long_endo"], r_long_epi=parameters["r_long_epi"], quota_base=parameters["quota_base"], psize=parameters["mesh_generation"]["psize"], ndiv=parameters["mesh_generation"]["ndiv"], ) geo: HeartGeometry = gmsh2dolfin(msh_name) msh_name.unlink() obj = cls( mesh=geo.mesh, marker_functions=geo.marker_functions, markers=geo.markers, ) obj._parameters = parameters # microstructure mspace = obj._parameters["microstructure"]["function_space"] dolfin.info("Creating microstructure") # coordinate mapping cart2coords_code = obj._compile_cart2coords_code() cart2coords = dolfin.compile_cpp_code(cart2coords_code) cart2coords_expr = dolfin.CompiledExpression( cart2coords.SimpleEllipsoidCart2Coords(), degree=1, ) # local coordinate base localbase_code = obj._compile_localbase_code() localbase = dolfin.compile_cpp_code(localbase_code) localbase_expr = dolfin.CompiledExpression( localbase.SimpleEllipsoidLocalCoords( cart2coords_expr.cpp_object()), degree=1, ) # function space family, degree = mspace.split("_") degree = int(degree) V = dolfin.TensorFunctionSpace(obj.mesh, family, degree, shape=(3, 3)) # microstructure expression alpha_endo = obj._parameters["microstructure"]["alpha_endo"] alpha_epi = obj._parameters["microstructure"]["alpha_epi"] microstructure_code = obj._compile_microstructure_code() microstructure = dolfin.compile_cpp_code(microstructure_code) microstructure_expr = dolfin.CompiledExpression( microstructure.EllipsoidMicrostructure( cart2coords_expr.cpp_object(), localbase_expr.cpp_object(), alpha_epi, alpha_endo, ), degree=1, ) # interpolation W = dolfin.VectorFunctionSpace(obj.mesh, family, degree) microinterp = interpolate(microstructure_expr, V) s0 = project(microinterp[0, :], W) n0 = project(microinterp[1, :], W) f0 = project(microinterp[2, :], W) obj.microstructure = Microstructure(f0=f0, s0=s0, n0=n0) obj.update_xshift() return obj
return "superlu_dist"; #elif PETSC_HAVE_PASTIX return "pastix"; #else throw std::logic_error("No suitable solver for parallel LU found"); #endif } } """ if has_pybind11(): cpp_code = "".join([ """ #include <petscksp.h> #include <dolfin/common/MPI.h> #include <pybind11/pybind11.h> """, cpp_code, """ PYBIND11_MODULE(SIGNATURE, m) { m.def("get_default_linear_solver", &get_default_linear_solver); } """ ]) get_default_linear_solver = compile_cpp_code( cpp_code).get_default_linear_solver else: get_default_linear_solver = compile_extension_module( cpp_code, additional_system_headers=["petscksp.h", "dolfin/common/MPI.h" ]).get_default_linear_solver
} values[0] = tau; }; }; PYBIND11_MODULE(SIGNATURE, m){ py::class_<SUPG, std::shared_ptr<SUPG>, dolfin::Expression> (m, "SUPG").def(py::init<std::shared_ptr<dolfin::Function>>()) .def("eval", &SUPG::eval) .def_readwrite("D", &SUPG::D); } ''' tau_code_compiled = df.compile_cpp_code(tau_code) tau_c = df.CompiledExpression(tau_code_compiled.SUPG(u_.cpp_object()), D=.1, element=r_.ufl_element()) # tau_c.value_rank() values = np.zeros(2) x = np.array([0.5, 0.5]) tau_c.eval(values, x) print(df.assemble(tau_c*df.dx(domain=mesh))) tau = df.interpolate(tau_c, Q) df.plot(tau) plt.show()
double R = sqrt(pow(x[0],2)+pow(x[1],2)); double phi = atan2(x[1],x[0]); double d_0 = C_9 + C_2*cyl_bessel_k(0, R*lambda_2/tau) + C_8*cyl_bessel_i(0, R*lambda_2/tau); double d = - (10*A_1 * pow(R,2))/(27*tau) + (4*C_4*R)/(tau) - (2*C_5*tau)/R + C_14*cyl_bessel_k(1, R*lambda_2/tau) + C_15* cyl_bessel_i(1, R*lambda_2/tau); values[0] = d_0 + cos(phi) * d; } // The data stored in mesh functions double R; }; PYBIND11_MODULE(SIGNATURE, m) { py::class_<Pressure, std::shared_ptr<Pressure>, dolfin::Expression> (m, "Pressure") .def(py::init<>()); } """ c = df.CompiledExpression(df.compile_cpp_code(p_code).Pressure(), degree=1) print(2 * c([1, 1])) p_i = df.interpolate(c, V) df.plot(p_i) file = df.File("out.pvd") file.write(p_i)
from dolfin import SystemAssembler, assemble, NewtonSolver, PETScFactory, NonlinearProblem, compile_cpp_code _cpp = """ #include <pybind11/pybind11.h> #include <dolfin/nls/NewtonSolver.h> PYBIND11_MODULE(SIGNATURE, m) { pybind11::class_<dolfin::NewtonSolver, std::shared_ptr<dolfin::NewtonSolver>> (m, "NewtonSolverExt", pybind11::module_local()) .def("krylov_iterations", &dolfin::NewtonSolver::krylov_iterations); } """ NewtonSolver.krylov_iterations = compile_cpp_code( _cpp).NewtonSolverExt.krylov_iterations class rmtursAssembler(object): def __init__(self, a, L, bcs, a_pc=None): self.assembler = SystemAssembler(a, L, bcs) if a_pc is not None: self.assembler_pc = SystemAssembler(a_pc, L, bcs) else: self.assembler_pc = None self._bcs = bcs def rhs_vector(self, b, x=None): if x is not None: self.assembler.assemble(b, x) else: self.assembler.assemble(b)
def evaluate_basis_functions(V, positions, cell_indices, factors): """ Current FEniCS pybind11 bindings lack wrappers for these functions, so a small C++ snippet is used to generate the necessary dof factors to evaluate a function at the given points """ if evaluate_basis_functions.func is None: cpp_code = """ #include <vector> #include <pybind11/pybind11.h> #include <pybind11/eigen.h> #include <pybind11/numpy.h> #include <dolfin/fem/FiniteElement.h> #include <dolfin/function/FunctionSpace.h> #include <dolfin/mesh/Mesh.h> #include <dolfin/mesh/Cell.h> #include <Eigen/Core> using IntVecIn = Eigen::Ref<const Eigen::VectorXi>; using RowMatrixXd = Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>; namespace py = pybind11; void dof_factors(const dolfin::FunctionSpace &V, const RowMatrixXd &positions, const IntVecIn &cell_indices, Eigen::Ref<RowMatrixXd> out) { const int N = out.rows(); if (N == 0) return; const auto &element = V.element(); const auto &mesh = V.mesh(); const auto &ufc_element = element->ufc_element(); std::vector<double> coordinate_dofs; const std::size_t size = ufc_element->value_size(); const std::size_t space_dimension = ufc_element->space_dimension(); if (size * space_dimension != out.cols()) throw std::length_error("ERROR: out.cols() != ufc element size * ufc element space_dimension"); for (int i = 0; i < N; i++) { int cell_index = cell_indices(i); dolfin::Cell cell(*mesh, cell_index); cell.get_coordinate_dofs(coordinate_dofs); element->evaluate_basis_all(out.row(i).data(), positions.row(i).data(), coordinate_dofs.data(), cell.orientation()); } } PYBIND11_MODULE(SIGNATURE, m) { m.def("dof_factors", &dof_factors, py::arg("V"), py::arg("positions"), py::arg("cell_indices"), py::arg("out").noconvert()); } """ evaluate_basis_functions.func = dolfin.compile_cpp_code(cpp_code).dof_factors assert len(cell_indices) == len(positions) == len(factors) evaluate_basis_functions.func(V._cpp_object, positions, cell_indices, factors)
# terms of the GNU General Public License (as published by the Free # Software Foundation) version 2.0 dated June 1991. import dolfin as dl import ufl import numpy as np import os abspath = os.path.dirname(os.path.abspath(__file__)) source_directory = os.path.join(abspath, "cpp_AssemblePointwiseObservation") with open(os.path.join(source_directory, "AssemblePointwiseObservation.cpp"), "r") as cpp_file: cpp_code = cpp_file.read() include_dirs = [".", source_directory] cpp_module = dl.compile_cpp_code(cpp_code, include_dirs=include_dirs) def assemblePointwiseObservation(Vh, targets, prune_and_sort=False): """ Assemble the pointwise observation matrix: Inputs - :code:`Vh`: FEniCS finite element space. - :code:`targets`: observation points (numpy array). """ #Ensure that PetscInitialize is called dummy = dl.assemble( ufl.inner(dl.TrialFunction(Vh), dl.TestFunction(Vh)) * ufl.dx) #Call the cpp module to compute the pointwise observation matrix
from dolfin import SubSystemsManager SubSystemsManager.init_petsc() # init PETSc by DOLFIN before petsc4py import from petsc4py import PETSc PETSc.Sys.pushErrorHandler("traceback") del SubSystemsManager, PETSc # Import public API from fenapack.field_split import PCDKSP, PCDKrylovSolver from fenapack.assembling import PCDAssembler, PCDForm from fenapack.nonlinear_solvers import PCDNewtonSolver, PCDNonlinearProblem from fenapack.preconditioners import PCDPC_BRM1, PCDPC_BRM2 from fenapack.preconditioners import PCDRPC_BRM1, PCDRPC_BRM2 from fenapack.stabilization import StabilizationParameterSD # Monkey patch dolfin.NewtonSolver in 2018.1.0 from dolfin import NewtonSolver, compile_cpp_code _cpp = """ #include <pybind11/pybind11.h> #include <dolfin/nls/NewtonSolver.h> PYBIND11_MODULE(SIGNATURE, m) { pybind11::class_<dolfin::NewtonSolver, std::shared_ptr<dolfin::NewtonSolver>> (m, "NewtonSolverExt", pybind11::module_local()) .def("krylov_iterations", &dolfin::NewtonSolver::krylov_iterations); } """ NewtonSolver.krylov_iterations = compile_cpp_code(_cpp).NewtonSolverExt.krylov_iterations del _cpp, NewtonSolver, compile_cpp_code