27 template <
typename ShapeFunction,
typename IntegrationMethod,
int GlobalDim>
30 ShapeFunction, IntegrationMethod, GlobalDim>
33 ShapeFunction, IntegrationMethod, GlobalDim>;
39 bool is_axially_symmetric,
40 unsigned const integration_order,
42 :
Base(e, is_axially_symmetric, integration_order),
_data(data)
46 void assemble(std::size_t
const boundary_element_id,
48 double const t, std::vector<GlobalVector*>
const& x,
57 unsigned const num_integration_points =
61 auto const num_comp_total =
64 auto const& bulk_node_ids_map =
66 .template getPropertyVector<std::size_t>(
70 Eigen::MatrixXd primary_variables_mat(num_nodes, num_comp_total);
71 for (
int var = 0; var < num_var; ++var)
75 for (
int comp = 0; comp < num_comp; ++comp)
77 auto const global_component =
80 for (
unsigned element_node_id = 0; element_node_id < num_nodes;
83 auto const*
const node =
85 auto const boundary_node_id = node->
getID();
86 auto const bulk_node_id =
87 bulk_node_ids_map[boundary_node_id];
97 "No d.o.f. found for (node={:d}, var={:d}, "
99 "That might be due to the use of mixed FEM ansatz "
100 "functions, which is currently not supported by "
101 "the implementation of Python BCs. That excludes, "
102 "e.g., the HM process.",
103 bulk_node_id, var, comp);
105 primary_variables_mat(element_node_id, global_component) =
106 (*x[process_id])[dof_idx];
111 Eigen::VectorXd local_rhs = Eigen::VectorXd::Zero(num_nodes);
112 Eigen::MatrixXd local_Jac =
113 Eigen::MatrixXd::Zero(num_nodes, num_nodes * num_comp_total);
114 std::vector<double> prim_vars_data(num_comp_total);
117 for (
unsigned ip = 0; ip < num_integration_points; ip++)
121 auto const coords = fe.interpolateCoordinates(N);
123 N * primary_variables_mat;
125 auto const flag_flux_dFlux =
134 if (!std::get<0>(flag_flux_dFlux))
140 auto const flux = std::get<1>(flag_flux_dFlux);
141 auto const& dFlux = std::get<2>(flag_flux_dFlux);
143 local_rhs.noalias() += N * (flux * w);
145 if (
static_cast<int>(dFlux.size()) != num_comp_total)
151 "The Python BC must return the derivative of the flux "
152 "w.r.t. each primary variable. {:d} components expected. "
153 "{:d} components returned from Python.",
154 num_comp_total, dFlux.size());
159 for (
int comp = 0; comp < num_comp_total; ++comp)
162 auto const left = comp * num_nodes;
163 auto const width = num_nodes;
164 auto const height = num_nodes;
167 local_Jac.block(top, left, width, height).noalias() -=
168 N.transpose() * (dFlux[comp] * w) * N;
173 auto const& indices_specific_component =
176 b.
add(indices_specific_component, local_rhs);
181 auto const indices_all_components =
184 indices_specific_component, indices_all_components};
185 Jac->
add(rci, local_Jac);
int add(IndexType row, IndexType col, double val)
Global vector based on Eigen vector.
void add(IndexType rowId, double v)
add entry
std::size_t getID() const
virtual const Node * getNode(unsigned idx) const =0
virtual unsigned getNumberOfNodes() const =0
Properties & getProperties()
int getGlobalComponent(int const variable_id, int const component_id) const
int getNumberOfVariables() const
GlobalIndexType getGlobalIndex(MeshLib::Location const &l, int const variable_id, int const component_id) const
int getNumberOfVariableComponents(int variable_id) const
int getNumberOfGlobalComponents() const
static NUMLIB_EXPORT GlobalIndexType const nop
MeshLib::Element const & _element
IntegrationMethod const _integration_method
std::vector< NAndWeight, Eigen::aligned_allocator< NAndWeight > > const _ns_and_weights
void assemble(std::size_t const boundary_element_id, NumLib::LocalToGlobalIndexMap const &dof_table_boundary, double const t, std::vector< GlobalVector * > const &x, int const process_id, GlobalMatrix &, GlobalVector &b, GlobalMatrix *Jac) override
PythonBoundaryConditionLocalAssembler(MeshLib::Element const &e, std::size_t const, bool is_axially_symmetric, unsigned const integration_order, PythonBoundaryConditionData const &data)
PythonBoundaryConditionData const & _data
bool isOverriddenNatural() const
virtual std::tuple< bool, double, std::vector< double > > getFlux(double, std::array< double, 3 >, std::vector< double > const &) const
Eigen::Map< const Vector > toVector(std::vector< double > const &data, Eigen::VectorXd::Index size)
Creates an Eigen mapped vector from the given data vector.
NumLib::TemplateIsoparametric< ShapeFunction, ShapeMatricesType > createIsoparametricFiniteElement(MeshLib::Element const &e)
std::vector< GlobalIndexType > getIndices(std::size_t const mesh_item_id, NumLib::LocalToGlobalIndexMap const &dof_table)
NumLib::LocalToGlobalIndexMap const & dof_table_bulk
DOF table of the entire domain.
PythonBoundaryConditionPythonSideInterface * bc_object
Python object computing BC values.
const MeshLib::Mesh & boundary_mesh
The boundary mesh, i.e., the domain of this BC.
int const global_component_id
std::size_t const bulk_mesh_id
Mesh ID of the entire domain.