38 return Eigen::MatrixXd::Zero(
get_mesh().dimension(),
get_mesh().dimension());
50 assert(
get_args()[
"boundary_conditions"].contains(bc_type) &&
"Requested boundary-condition type must exist");
52 std::unordered_map<int, std::array<bool, 3>> bcs;
53 for (
const json &bc : json_bcs)
55 assert(bc[
"dimension"].size() >=
get_mesh().dimension() &&
"Boundary-condition dimensions must cover the mesh dimension");
56 std::array<bool, 3> dimension{{
true,
true,
true}};
57 for (
int d = 0; d < bc[
"dimension"].size(); ++d)
58 dimension[d] = bc[
"dimension"][d];
59 assert(bc.contains(
"id") && bc[
"id"].is_number_integer() &&
"Boundary conditions must have an integer id");
60 bcs[bc[
"id"].get<
int>()] = dimension;
67 return get_args().contains(
"/constraints/macro_displacement_gradient"_json_pointer);
72 return get_args().contains(
"/boundary_conditions/periodic"_json_pointer)
73 && !
get_args().at(
"/boundary_conditions/periodic"_json_pointer).empty();
79 const json &conditions =
get_args().at(
"/boundary_conditions/periodic"_json_pointer);
80 Eigen::MatrixXd offsets(dim, conditions.size());
81 for (
int i = 0; i < int(conditions.size()); ++i)
83 const json &condition = conditions[i];
84 if (!condition.contains(
"boundary_ids")
85 || !condition[
"boundary_ids"].is_array()
86 || condition[
"boundary_ids"].size() != 2)
89 "Periodic boundary condition {} must contain exactly two boundary_ids.", i);
91 const std::array<int, 2> boundary_ids = {{condition[
"boundary_ids"][0].get<
int>(),
92 condition[
"boundary_ids"][1].get<int>()}};
96 boundary_ids, condition.value(
"tolerance", 1e-5));
97 offsets.col(i) = mapping.translation.transpose();
104 return get_args()[
"contact"][
"adhesion"][
"adhesion_enabled"];
109 return !
get_args()[
"boundary_conditions"][
"pressure_boundary"].empty()
110 || !
get_args()[
"boundary_conditions"][
"pressure_cavity"].empty();
115 return !
get_args()[
"constraints"][
"hard"].empty()
116 || !
get_args()[
"constraints"][
"soft"].empty();
135 assert(space.
geometry &&
"Node mapping requires an initialized geometry mapping");
136 const auto &mesh_nodes = space.
geometry->mesh_nodes;
139 std::vector<int> indices = mesh_nodes->primitive_to_node();
140 assert(indices.size() >=
get_mesh().n_vertices() &&
"Primitive-to-node mapping must contain every mesh vertex");
141 indices.resize(
get_mesh().n_vertices());
148 assert(
primary_space().geometry &&
"Node mapping requires an initialized geometry mapping");
149 assert(
primary_space().geometry->
n_bases == p2n.size() &&
"Optimization requires first-order geometry bases");
150 std::vector<int> indices(p2n.size());
151 for (
int i = 0; i < p2n.size(); ++i)
153 assert(p2n[i] >= 0 && p2n[i] < indices.size() &&
"Primitive-to-node entries must be valid node indices");
165 elements.resize(geometry_bases.size(),
get_mesh().dimension() + 1);
166 for (
int e = 0; e < geometry_bases.size(); ++e)
169 for (
const auto &basis : geometry_bases[e].bases)
170 elements(e, i++) = n2p[basis.global()[0].index];
177 assert(space.
disc_orders.size() > 0 &&
"Boundary quadrature requires initialized FE orders");
178 assert(space.
geometry &&
"Boundary quadrature requires an initialized geometry mapping");
179 assert(space.
geometry->disc_orders.size() > 0 &&
"Boundary quadrature requires initialized geometry orders");
189 "Invalid vertex matrix shape ({}, {}), expected ({}, {}).",
191 for (
int i = 0; i < vertices.rows(); ++i)
198 if (lambda.size() !=
get_mesh().n_elements() || mu.size() !=
get_mesh().n_elements())
206 get_args()[
"contact"][
"friction_coefficient"] = coefficient;
212 auto update_material = [psi, phi](
json &material) {
213 material[
"psi"] = psi;
214 material[
"phi"] = phi;
216 if (
get_args()[
"materials"].is_array())
218 for (
auto &material :
get_args()[
"materials"])
219 update_material(material);
222 update_material(
get_args()[
"materials"]);
231 tensor_problem->update_dirichlet_boundary(boundary_id, time_step, value);
240 tensor_problem->update_dirichlet_nodes(
primary_space().space_in_node_to_node, input_nodes, values);
249 tensor_problem->update_pressure_boundary(boundary_id, time_step, value);
virtual void assemble(const bool is_volume, const int n_basis, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const AssemblyValsCache &cache, const double t, StiffnessMatrix &stiffness, const bool is_mass=false) const
virtual bool is_linear() const =0
Abstract mesh class to capture 2d/3d conforming and non-conforming meshes.
virtual int n_vertices() const =0
number of vertices
virtual void set_point(const int global_index, const RowVectorNd &p)=0
Set the point.
virtual RowVectorNd point(const int global_index) const =0
point coordinates
const Eigen::MatrixXi & orders() const
order of each element
int dimension() const
utily for dimension
std::vector< T > json_as_array(const json &j)
Return the value of a json object as an array.
std::array< int, 2 > QuadratureOrders
void log_and_throw_adjoint_error(const std::string &msg)
void log_and_throw_error(const std::string &msg)
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix