43 return Eigen::MatrixXd::Zero(
get_mesh().dimension(),
get_mesh().dimension());
55 assert(
get_args()[
"boundary_conditions"].contains(bc_type) &&
"Requested boundary-condition type must exist");
57 std::unordered_map<int, std::array<bool, 3>> bcs;
58 for (
const json &bc : json_bcs)
60 assert(bc[
"dimension"].size() >=
get_mesh().dimension() &&
"Boundary-condition dimensions must cover the mesh dimension");
61 std::array<bool, 3> dimension{{
true,
true,
true}};
62 for (
int d = 0; d < bc[
"dimension"].size(); ++d)
63 dimension[d] = bc[
"dimension"][d];
64 assert(bc.contains(
"id") && bc[
"id"].is_number_integer() &&
"Boundary conditions must have an integer id");
65 bcs[bc[
"id"].get<
int>()] = dimension;
72 return get_args().contains(
"/constraints/macro_displacement_gradient"_json_pointer);
77 return get_args().contains(
"/boundary_conditions/periodic"_json_pointer)
78 && !
get_args().at(
"/boundary_conditions/periodic"_json_pointer).empty();
84 const json &conditions =
get_args().at(
"/boundary_conditions/periodic"_json_pointer);
85 Eigen::MatrixXd offsets(dim, conditions.size());
86 for (
int i = 0; i < int(conditions.size()); ++i)
88 const json &condition = conditions[i];
89 if (!condition.contains(
"boundary_ids")
90 || !condition[
"boundary_ids"].is_array()
91 || condition[
"boundary_ids"].size() != 2)
94 "Periodic boundary condition {} must contain exactly two boundary_ids.", i);
96 const std::array<int, 2> boundary_ids = {{condition[
"boundary_ids"][0].get<
int>(),
97 condition[
"boundary_ids"][1].get<int>()}};
101 boundary_ids, condition.value(
"tolerance", 1e-5));
102 offsets.col(i) = mapping.translation.transpose();
109 return get_args()[
"contact"][
"adhesion"][
"adhesion_enabled"];
114 return !
get_args()[
"boundary_conditions"][
"pressure_boundary"].empty()
115 || !
get_args()[
"boundary_conditions"][
"pressure_cavity"].empty();
120 return !
get_args()[
"constraints"][
"hard"].empty()
121 || !
get_args()[
"constraints"][
"soft"].empty();
140 assert(space.
geometry &&
"Node mapping requires an initialized geometry mapping");
141 const auto &mesh_nodes = space.
geometry->mesh_nodes;
144 std::vector<int> indices = mesh_nodes->primitive_to_node();
145 assert(indices.size() >=
get_mesh().n_vertices() &&
"Primitive-to-node mapping must contain every mesh vertex");
146 indices.resize(
get_mesh().n_vertices());
153 assert(
primary_space().geometry &&
"Node mapping requires an initialized geometry mapping");
154 assert(
primary_space().geometry->
n_bases == p2n.size() &&
"Optimization requires first-order geometry bases");
155 std::vector<int> indices(p2n.size());
156 for (
int i = 0; i < p2n.size(); ++i)
158 assert(p2n[i] >= 0 && p2n[i] < indices.size() &&
"Primitive-to-node entries must be valid node indices");
170 elements.resize(geometry_bases.size(),
get_mesh().dimension() + 1);
171 for (
int e = 0; e < geometry_bases.size(); ++e)
174 for (
const auto &basis : geometry_bases[e].bases)
175 elements(e, i++) = n2p[basis.global()[0].index];
182 assert(space.
disc_orders.size() > 0 &&
"Boundary quadrature requires initialized FE orders");
183 assert(space.
geometry &&
"Boundary quadrature requires an initialized geometry mapping");
184 assert(space.
geometry->disc_orders.size() > 0 &&
"Boundary quadrature requires initialized geometry orders");
194 "Invalid vertex matrix shape ({}, {}), expected ({}, {}).",
196 for (
int i = 0; i < vertices.rows(); ++i)
203 if (lambda.size() !=
get_mesh().n_elements() || mu.size() !=
get_mesh().n_elements())
211 get_args()[
"contact"][
"friction_coefficient"] = coefficient;
217 auto update_material = [psi, phi](
json &material) {
218 material[
"psi"] = psi;
219 material[
"phi"] = phi;
221 if (
get_args()[
"materials"].is_array())
223 for (
auto &material :
get_args()[
"materials"])
224 update_material(material);
227 update_material(
get_args()[
"materials"]);
236 tensor_problem->update_dirichlet_boundary(boundary_id, time_step, value);
245 tensor_problem->update_dirichlet_nodes(
primary_space().space_in_node_to_node, input_nodes, values);
254 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