14#include <pybind11/pybind11.h>
28 std::size_t
const nnodes)
30 bc_values.
ids.clear();
33 bc_values.
ids.reserve(nnodes);
34 bc_values.
values.reserve(nnodes);
39 std::vector<std::reference_wrapper<ProcessLib::ProcessVariable>>
const& pvs)
42 auto const num_vars_pv = pvs.size();
44 if (
static_cast<std::size_t
>(num_vars_dt) != num_vars_pv)
47 "The number of variables in the d.o.f. table does not match the "
48 "number of process variables: {} != {}.",
49 num_vars_dt, num_vars_pv);
52 for (std::size_t var = 0; var < num_vars_pv; ++var)
55 auto const num_comp_pv = pvs[var].get().getNumberOfGlobalComponents();
57 if (num_comp_dt != num_comp_pv)
60 "The number of components of variable #{} in the d.o.f. table "
61 "does not match the number of components of process variable "
62 "#{} ({}): {} != {}.",
63 var, var, pvs[var].get().
getName(), num_vars_dt, num_vars_pv);
72 PythonBcData&& bc_data,
unsigned const integration_order,
73 bool const flush_stdout,
unsigned const bulk_mesh_dimension,
75 : _bc_data(std::move(bc_data)), _flush_stdout(flush_stdout)
77 checkConsistency(dof_table_bulk,
80 std::vector<MeshLib::Node*>
const& bc_nodes =
103 auto const& boundary_nodes = boundary_mesh.
getNodes();
106 initBCValues(bc_values, boundary_nodes.size());
108 std::vector<double> primary_variables;
112 for (
auto const* boundary_node : boundary_nodes)
114 auto const boundary_node_id = boundary_node->getID();
115 auto const dof_idx =
getDofIdx(boundary_node_id);
135 auto const [apply_bc, bc_value] = bc_object->getDirichletBCValue(
137 {(*boundary_node)[0], (*boundary_node)[1], (*boundary_node)[2]},
138 boundary_node_id, primary_variables);
140 if (!bc_object->isOverriddenEssential())
143 "Method `getDirichletBCValue' not overridden in Python "
153 bc_values.
ids.emplace_back(dof_idx);
154 bc_values.
values.emplace_back(bc_value);
157 catch (pybind11::error_already_set
const& e)
159 OGS_FATAL(
"Error evaluating Dirichlet BC in Python: {}", e.what());
164 std::size_t
const boundary_node_id)
const
173 std::size_t
const boundary_node_id,
int const var,
int const comp)
const
181 std::vector<double>& primary_variables,
MeshLib::Node const& boundary_node,
184 primary_variables.clear();
186 auto const boundary_node_id = boundary_node.
getID();
188 for (
int var = 0; var < num_var; ++var)
190 auto const num_comp =
192 for (
int comp = 0; comp < num_comp; ++comp)
194 auto const dof_idx =
getDofIdx(boundary_node_id, var, comp);
196 double const pv_value =
201 primary_variables.push_back(pv_value);
210 auto const& boundary_elements =
212 boundary_node.
getID());
214 if (boundary_elements.size() != 1)
217 "Boundary node {} is associated with {} elements in the boundary "
219 boundary_node.
getID(),
220 boundary_elements.size());
225 auto const& boundary_element = *boundary_elements.front();
227 assert(boundary_element.getNumberOfBaseNodes() <
228 boundary_element.getNumberOfNodes() &&
229 "We expect that the boundary element is a higher order element. "
230 "Otherwise no interpolation should take place.");
233 auto const local_node_id_within_boundary_element =
234 getNodeIDinElement(boundary_element, &boundary_node);
236 auto const boundary_element_id = boundary_element.getID();
242 return loc_asm.interpolate(local_node_id_within_boundary_element,
247 const double t, std::vector<GlobalVector*>
const& x,
int const process_id,
261 DBUG(
"Method `getFlux' not overridden in Python script.");
263 catch (pybind11::error_already_set
const& e)
265 OGS_FATAL(
"Error evaluating natural BC in Python: {}", e.what());
273 int const component_id,
unsigned const integration_order,
274 unsigned const shapefunction_order,
275 std::vector<std::reference_wrapper<ProcessVariable>>
const&
276 all_process_variables_for_this_process)
287 pybind11::object scope =
288 pybind11::module::import(
"__main__").attr(
"__dict__");
290 if (!scope.contains(bc_object))
293 "Function `{:s}' is not defined in the python script file, or "
294 "there was no python script file specified.",
298 auto* bc = scope[bc_object.c_str()]
307 "Variable id or component id too high. Actual values: ({:d}, "
308 "{:d}), maximum values: ({:d}, {:d}).",
328 return std::make_unique<PythonBoundaryCondition>(
331 boundary_mesh, all_process_variables_for_this_process,
332 shapefunction_order}},
333 integration_order, flush_stdout, bulk_mesh.
getDimension(),
GlobalMatrix::IndexType GlobalIndexType
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
T getConfigParameter(std::string const ¶m) const
void checkConfigParameter(std::string const ¶m, std::string_view const value) const
Global vector based on Eigen vector.
std::size_t getID() const
A subset of nodes on a single mesh.
bool isAxiallySymmetric() const
std::vector< Node * > const & getNodes() const
Get the nodes-vector for the mesh.
std::vector< Element * > const & getElements() const
Get the element-vector for the mesh.
unsigned getDimension() const
Returns the dimension of the mesh (determined by the maximum dimension over all elements).
std::size_t getID() const
Get id of the mesh.
std::size_t getNumberOfNodes() const
Get the number of nodes.
std::vector< Element const * > const & getElementsConnectedToNode(std::size_t node_id) const
std::size_t getNumberOfElements() const
Get the number of elements.
int getGlobalComponent(int const variable_id, int const component_id) const
int getNumberOfVariables() const
int getNumberOfVariableComponents(int variable_id) const
std::unique_ptr< LocalToGlobalIndexMap > deriveBoundaryConstrainedMap(int const variable_id, std::vector< int > const &component_ids, MeshLib::MeshSubset &&new_mesh_subset) const
static constexpr NUMLIB_EXPORT GlobalIndexType const nop
virtual void assemble(std::size_t const id, NumLib::LocalToGlobalIndexMap const &dof_table_boundary, double const t, std::vector< GlobalVector * > const &x, int const process_id, GlobalMatrix *K, GlobalVector &b, GlobalMatrix *Jac)=0
std::unique_ptr< NumLib::LocalToGlobalIndexMap > _dof_table_boundary
Local dof table for the boundary mesh.
double interpolateToHigherOrderNode(GlobalVector const &x, int const var, int const comp, MeshLib::Node const &boundary_node) const
PythonBcData _bc_data
Auxiliary data used by the local assemblers.
void applyNaturalBC(const double t, std::vector< GlobalVector * > const &x, int const process_id, GlobalMatrix *K, GlobalVector &b, GlobalMatrix *Jac) override
std::vector< std::unique_ptr< PythonBoundaryConditionLocalAssemblerInterface > > _local_assemblers
Local assemblers for all elements of the boundary mesh.
void getEssentialBCValues(const double t, const GlobalVector &x, NumLib::IndexValueVector< GlobalIndexType > &bc_values) const override
Writes the values of essential BCs to bc_values.
GlobalIndexType getDofIdx(std::size_t const boundary_node_id) const
void collectPrimaryVariables(std::vector< double > &primary_variables, MeshLib::Node const &boundary_node, GlobalVector const &x) const
PythonBoundaryCondition(PythonBcData &&bc_data, unsigned const integration_order, bool const flush_stdout, unsigned const bulk_mesh_dimension, NumLib::LocalToGlobalIndexMap const &dof_table_bulk)
void createLocalAssemblersPython(const unsigned dimension, std::vector< MeshLib::Element * > const &mesh_elements, NumLib::LocalToGlobalIndexMap const &dof_table, std::vector< std::unique_ptr< LocalAssemblerInterface > > &local_assemblers, NumLib::IntegrationOrder const integration_order, ExtraCtorArgs &&... extra_ctor_args)
std::unique_ptr< PythonBoundaryCondition > createPythonBoundaryCondition(BaseLib::ConfigTree const &config, MeshLib::Mesh const &boundary_mesh, NumLib::LocalToGlobalIndexMap const &dof_table_bulk, MeshLib::Mesh const &bulk_mesh, int const variable_id, int const component_id, unsigned const integration_order, unsigned const shapefunction_order, std::vector< std::reference_wrapper< ProcessVariable > > const &all_process_variables_for_this_process)
Creates a new PythonBoundaryCondition object.
void checkConsistency(NumLib::LocalToGlobalIndexMap const &dof_table, std::vector< std::reference_wrapper< ProcessLib::ProcessVariable > > const &pvs)
void initBCValues(NumLib::IndexValueVector< GlobalIndexType > &bc_values, std::size_t const nnodes)
std::vector< IndexType > ids
std::vector< double > values
static void executeMemberOnDereferenced(Method method, Container const &container, Args &&... args)
MeshLib::Mesh const & bc_or_st_mesh
The domain, where this BC or ST will be applied.
std::vector< std::reference_wrapper< ProcessVariable > > const & all_process_variables_for_this_process
int const global_component_id
BcOrStPythonSideInterface const *const bc_or_st_object
Python object computing BC or ST values.