28 unsigned const integration_order,
MeshLib::Mesh const& bulk_mesh,
29 double const constraint_threshold,
bool const lower,
32 std::vector<GlobalVector*>
const&)>
34 : _parameter(parameter),
35 _variable_id(variable_id),
36 _component_id(component_id),
38 _integration_order(integration_order),
39 _constraint_threshold(constraint_threshold),
41 _bulk_mesh(bulk_mesh),
50 "Variable id or component id too high. Actual values: ({:d}, "
51 "{:d}), maximum values: ({:d}, {:d}).",
52 variable_id, component_id, dof_table_bulk.getNumberOfVariables(),
53 dof_table_bulk.getNumberOfVariableComponents(variable_id));
58 "Found {:d} nodes for constraint Dirichlet BCs for the variable {:d} "
60 bc_nodes.size(), variable_id, component_id);
67 variable_id, {component_id}, std::move(bc_mesh_subset));
75 auto const& bulk_nodes = bulk_mesh.
getNodes();
77 auto get_bulk_element_face_id =
80 auto const* bulk_elem = _bulk_mesh.getElement(bulk_element_id);
81 std::array<MeshLib::Node const*, 3> nodes{
82 {bulk_nodes[(*bulk_node_ids)[bc_elem->getNode(0)->getID()]],
83 bulk_nodes[(*bulk_node_ids)[bc_elem->getNode(1)->getID()]],
84 bulk_nodes[(*bulk_node_ids)[bc_elem->getNode(2)->getID()]]}};
85 return bulk_elem->identifyFace(nodes.data());
88 _bulk_ids.reserve(bc_elements.size());
90 begin(bc_elements), end(bc_elements), std::back_inserter(_bulk_ids),
91 [&](
auto const* bc_element)
93 auto const bulk_element_id =
94 (*bulk_element_ids)[bc_element->getID()];
95 return std::make_pair(
97 get_bulk_element_face_id(bulk_element_id, bc_element));
100 const int shape_function_order = 1;
103 ConstraintDirichletBoundaryConditionLocalAssembler>(
104 _bulk_mesh.getDimension(), _bc_mesh.getElements(), *_dof_table_boundary,
105 shape_function_order, _local_assemblers,
107 _bc_mesh.isAxiallySymmetric(), bulk_mesh, _bulk_ids);
110void ConstraintDirichletBoundaryCondition::preTimestep(
111 double const t, std::vector<GlobalVector*>
const& x,
115 "ConstraintDirichletBoundaryCondition::preTimestep: computing flux "
119 _flux_values[id] = _local_assemblers[id]->integrate(
122 double const t, std::vector<GlobalVector*>
const& x)
123 {
return _getFlux(element_id, pnt, t, x); });
127void ConstraintDirichletBoundaryCondition::getEssentialBCValues(
133 bc_values.
ids.clear();
136 std::vector<std::pair<GlobalIndexType, double>> tmp_bc_values;
138 auto isFlux = [&](
const std::size_t element_id)
140 return _lower ? _flux_values[element_id] < _constraint_threshold
141 : _flux_values[element_id] > _constraint_threshold;
144 for (
auto const* boundary_element : _bc_mesh.getElements())
147 if (isFlux(boundary_element->getID()))
153 unsigned const number_nodes = boundary_element->getNumberOfNodes();
154 for (
unsigned i = 0; i < number_nodes; ++i)
156 auto const id = boundary_element->getNode(i)->getID();
157 pos.
setAll(
id, boundary_element->getID(), {}, {});
162 const auto g_idx = _dof_table_boundary->getGlobalIndex(
163 l, _variable_id, _component_id);
177 tmp_bc_values.emplace_back(g_idx, _parameter(t, pos).front());
182 if (tmp_bc_values.empty())
184 DBUG(
"The domain on which the boundary is defined is empty");
192 std::sort(tmp_bc_values.begin(), tmp_bc_values.end(),
193 [](std::pair<GlobalIndexType, double>
const& a,
194 std::pair<GlobalIndexType, double>
const& b)
195 { return a.first < b.first; });
199 double sum = tmp_bc_values.begin()->second;
200 for (
auto const& tmp_bc_value : tmp_bc_values)
202 if (tmp_bc_value.first == current_id)
205 sum += tmp_bc_value.second;
209 bc_values.
ids.emplace_back(current_id);
210 bc_values.
values.emplace_back(sum / cnt);
212 sum = tmp_bc_value.second;
213 current_id = tmp_bc_value.first;
216 bc_values.
ids.emplace_back(current_id);
217 bc_values.
values.emplace_back(sum / cnt);
219 DBUG(
"Found {:d} constraint dirichlet boundary condition values.",
220 bc_values.
ids.size());
223std::unique_ptr<ConstraintDirichletBoundaryCondition>
227 unsigned const integration_order,
int const component_id,
228 std::vector<std::unique_ptr<ParameterLib::ParameterBase>>
const& parameters,
229 Process const& constraining_process)
231 DBUG(
"Constructing ConstraintDirichletBoundaryCondition from config.");
235 auto const constraint_type =
238 if (constraint_type !=
"Flux")
240 OGS_FATAL(
"The constraint type is '{:s}', but has to be 'Flux'.",
246 auto const constraining_process_variable =
253 "The constraint dirichlet boundary condition is implemented only "
254 "for monolithic implemented processes.");
256 const int process_id = 0;
257 auto process_variables =
259 auto constraining_pv =
260 std::find_if(process_variables.cbegin(), process_variables.cend(),
262 { return pv.getName() == constraining_process_variable; });
263 if (constraining_pv == std::end(process_variables))
265 auto const& constraining_process_variable_name =
266 process_variables[variable_id].get().getName();
268 "<constraining_process_variable> in process variable name '{:s}' "
269 "at geometry 'TODO' : The constraining process variable is set as "
270 "'{:s}', but this is not specified in the project file.",
271 constraining_process_variable_name,
272 constraining_process_variable);
275 auto const constraint_threshold =
279 auto const constraint_direction_string =
282 if (constraint_direction_string !=
"greater" &&
283 constraint_direction_string !=
"lower")
286 "The constraint direction is '{:s}', but has to be either "
287 "'greater' or 'lower'.",
288 constraint_direction_string);
290 bool const lower = constraint_direction_string ==
"lower";
294 DBUG(
"Using parameter {:s}", param_name);
313 return std::make_unique<ConstraintDirichletBoundaryCondition>(
314 param, dof_table_bulk, variable_id, component_id, bc_mesh,
315 integration_order, constraining_process.
getMesh(), constraint_threshold,
317 [&constraining_process](std::size_t
const element_id,
319 std::vector<GlobalVector*>
const& x)
320 { return constraining_process.getFlux(element_id, pnt, t, x); });
GlobalMatrix::IndexType GlobalIndexType
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
Definition of the Node class.
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.
A subset of nodes on a single mesh.
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 getNumberOfNodes() const
Get the number of nodes.
std::size_t getNumberOfElements() const
Get the number of elements.
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
void setAll(std::optional< std::size_t > const &node_id, std::optional< std::size_t > const &element_id, std::optional< unsigned > const &integration_point, std::optional< MathLib::Point3d > const &coordinates)
std::vector< std::unique_ptr< ConstraintDirichletBoundaryConditionLocalAssemblerInterface > > _local_assemblers
Local assemblers for each boundary element.
std::unique_ptr< NumLib::LocalToGlobalIndexMap > _dof_table_boundary
MeshLib::Mesh const & _bc_mesh
std::vector< double > _flux_values
Stores the results of the flux computations per boundary element.
ConstraintDirichletBoundaryCondition(ParameterLib::Parameter< double > const ¶meter, NumLib::LocalToGlobalIndexMap const &dof_table_bulk, int const variable_id, int const component_id, MeshLib::Mesh const &bc_mesh, unsigned const integration_order, MeshLib::Mesh const &bulk_mesh, double const constraint_threshold, bool const lower, std::function< Eigen::Vector3d(std::size_t const, MathLib::Point3d const &, double const, std::vector< GlobalVector * > const &)> getFlux)
MeshLib::Mesh & getMesh() const
virtual bool isMonolithicSchemeUsed() const
std::vector< std::vector< std::reference_wrapper< ProcessVariable > > > const & getProcessVariables() const
constexpr ranges::views::view_closure ids
For an element of a range view return its id.
PropertyVector< std::size_t > const * bulkElementIDs(Mesh const &mesh)
PropertyVector< std::size_t > const * bulkNodeIDs(Mesh const &mesh)
OGS_NO_DANGLING Parameter< ParameterDataType > & findParameter(std::string const ¶meter_name, std::vector< std::unique_ptr< ParameterBase > > const ¶meters, int const num_components, MeshLib::Mesh const *const mesh=nullptr)
void createLocalAssemblers(const unsigned dimension, std::vector< MeshLib::Element * > const &mesh_elements, NumLib::LocalToGlobalIndexMap const &dof_table, const unsigned shapefunction_order, std::vector< std::unique_ptr< LocalAssemblerInterface > > &local_assemblers, NumLib::IntegrationOrder const integration_order, ExtraCtorArgs &&... extra_ctor_args)
std::unique_ptr< ConstraintDirichletBoundaryCondition > createConstraintDirichletBoundaryCondition(BaseLib::ConfigTree const &config, MeshLib::Mesh const &bc_mesh, NumLib::LocalToGlobalIndexMap const &dof_table_bulk, int const variable_id, unsigned const integration_order, int const component_id, std::vector< std::unique_ptr< ParameterLib::ParameterBase > > const ¶meters, Process const &constraining_process)
std::vector< IndexType > ids
std::vector< double > values