7#include <igl/writeMESH.h>
9#include <geogram/mesh/mesh_io.h>
20 assert(keep.size() ==
n_cells());
22 std::vector<int> old_node_ids(
vertices.size(), -1);
26 std::vector<int> old_boundary_ids(
faces.size(), -1);
28 for (
int f = 0; f <
n_faces(); ++f)
31 for (
int e = 0; e < keep.size(); ++e)
37 element.is_ghost =
true;
38 for (
const int face : element.faces)
39 faces[face].remove_element(full_id);
40 for (
const int edge : element.edges)
41 edges[edge].remove_element(full_id);
42 for (
const int vertex : element.vertices)
43 vertices[vertex].remove_element(full_id);
58 for (
int f = 0; f <
n_faces(); ++f)
77 if (n_refinement <= 0)
79 std::vector<bool> refine_mask(
elements.size(),
false);
80 for (
int i = 0; i <
elements.size(); i++)
82 refine_mask[i] =
true;
84 for (
int i = 0; i < refine_mask.size(); i++)
88 refine(n_refinement - 1, t);
94 for (
int lv = 0; lv <
n_cell_edges(element_global_id); lv++)
115 for (
int i = 0; i <
V.rows(); i++)
119 for (
int i = 0; i <
F.rows(); i++)
131 for (
int f = 0; f <
n_cells(); ++f)
132 if (nodes[f].size() != 4)
133 throw std::runtime_error(
"NCMesh doesn't support high order mesh!");
141 auto extent = max - min;
142 double scale = extent.maxCoeff();
145 v.pos = (v.pos - min.transpose()) / scale;
205 for (
int d = 0; d < 3; d++)
207 if (v.pos[d] > max[d])
209 if (v.pos[d] < min[d])
220 for (
int f = 0; f <
n_faces(); ++f)
226 for (
int vid = 0; vid < vs.size(); ++vid)
229 std::sort(vs.begin(), vs.end());
241 for (
int e = 0; e <
n_cells(); ++e)
250 assert(boundary_ids.size() ==
n_faces());
251 for (
int i = 0; i < boundary_ids.size(); i++)
258 assert(body_ids.size() ==
n_cells());
259 for (
int i = 0; i < body_ids.size(); i++)
380 idx.element_patch = lf;
385 idx.face_corner = lv;
386 idx.vertex =
face_vertex(idx.face, idx.face_corner);
388 idx.edge =
face_edge(idx.face, idx.face_corner);
397 idx.element_patch = 0;
400 idx.vertex =
face_vertex(idx.face, idx.face_corner);
414 for (
int i = 0; i < 4; i++)
416 const int f_id =
cell_face(idx.element, i);
417 for (
int j = 0; j < 3; j++)
420 if (idx.edge == e_id)
422 idx.element_patch = i;
451 int v0_ = v0, v1_ = v1;
457 for (
int i = 0; i < 4; i++)
459 const int fid =
cell_face(idx.element, i);
463 idx.element_patch = i;
465 for (
int j = 0; j < 3; j++)
471 if ((ev0 == v0_ && ev1 == v1_) || (ev0 == v1_ && ev1 == v0_))
489 std::vector<uint32_t> hs;
497 std::vector<uint32_t> hs;
519 if (idx.edge ==
face_edge(idx.face, idx.face_corner))
520 idx.edge =
face_edge(idx.face, (idx.face_corner + 2) % 3);
522 idx.edge =
face_edge(idx.face, idx.face_corner);
527 for (
int i = 0; i < 4; i++)
529 const int fid =
cell_face(idx.element, i);
535 idx.element_patch = i;
549 if (face.n_elem() != 2)
560 if (
cell_face(idx.element, f) == idx.face)
561 idx.element_patch = f;
596 if (
elements[id_full].is_not_valid())
597 throw std::runtime_error(
"Cannot refine an invalid element!");
599 const auto v =
elements[id_full].vertices;
600 elements[id_full].is_refined =
true;
603 for (
int f = 0; f <
elements[id_full].faces.size(); f++)
606 for (
int e = 0; e <
elements[id_full].edges.size(); e++)
609 for (
int i = 0; i < v.size(); i++)
610 vertices[v(i)].remove_element(id_full);
612 if (
elements[id_full].children(0) >= 0)
614 for (
int c = 0; c <
elements[id_full].children.size(); c++)
616 const int child_id =
elements[id_full].children(c);
618 elem.is_ghost =
false;
621 for (
int f = 0; f < elem.faces.size(); f++)
622 faces[elem.faces(f)].add_element(child_id);
624 for (
int e = 0; e < elem.edges.size(); e++)
625 edges[elem.edges(e)].add_element(child_id);
627 for (
int v = 0; v < elem.vertices.size(); v++)
628 vertices[elem.vertices(v)].add_element(child_id);
638 const int v5 =
get_vertex(Eigen::Vector2i(v1, v2));
639 const int v8 =
get_vertex(Eigen::Vector2i(v3, v2));
640 const int v6 =
get_vertex(Eigen::Vector2i(v1, v3));
641 const int v7 =
get_vertex(Eigen::Vector2i(v1, v4));
642 const int v9 =
get_vertex(Eigen::Vector2i(v4, v2));
643 const int v10 =
get_vertex(Eigen::Vector2i(v3, v4));
646 for (
int i = 0; i < v.size(); i++)
647 for (
int j = 0; j < i; j++)
657 for (
int i = 0; i < v.size(); i++)
658 for (
int j = 0; j < i; j++)
659 for (
int k = 0; k < j; k++)
665 int facei =
get_face(v[i], vij, vik);
666 int facej =
get_face(v[j], vjk, vij);
667 int facek =
get_face(v[k], vjk, vik);
668 int facem =
get_face(vij, vjk, vik);
669 faces[facei].boundary_id =
faces[fid].boundary_id;
670 faces[facej].boundary_id =
faces[fid].boundary_id;
671 faces[facek].boundary_id =
faces[fid].boundary_id;
672 faces[facem].boundary_id =
faces[fid].boundary_id;
677 add_element(Eigen::Vector4i(v1, v5, v6, v7), id_full);
679 add_element(Eigen::Vector4i(v5, v2, v8, v9), id_full);
681 add_element(Eigen::Vector4i(v6, v8, v3, v10), id_full);
683 add_element(Eigen::Vector4i(v7, v9, v10, v4), id_full);
685 add_element(Eigen::Vector4i(v5, v6, v7, v9), id_full);
687 add_element(Eigen::Vector4i(v5, v9, v8, v6), id_full);
689 add_element(Eigen::Vector4i(v6, v7, v9, v10), id_full);
691 add_element(Eigen::Vector4i(v6, v10, v9, v8), id_full);
698 std::vector<int> full_ids(ids.size());
699 for (
int i = 0; i < ids.size(); i++)
702 for (
int i : full_ids)
708 const int parent_id =
elements[id_full].parent;
711 for (
int i = 0; i < parent.children.size(); i++)
712 if (
elements[parent.children(i)].is_not_valid())
713 throw std::runtime_error(
"Invalid siblings in coarsening!");
716 for (
int c = 0; c < parent.children.size(); c++)
718 auto &elem =
elements[parent.children(c)];
719 elem.is_ghost =
true;
722 for (
int f = 0; f < elem.faces.size(); f++)
723 faces[elem.faces(f)].remove_element(parent.children(c));
725 for (
int e = 0; e < elem.edges.size(); e++)
726 edges[elem.edges(e)].remove_element(parent.children(c));
728 for (
int v = 0; v < elem.vertices.size(); v++)
729 vertices[elem.vertices(v)].remove_element(parent.children(c));
733 parent.is_refined =
false;
736 for (
int f = 0; f < parent.faces.size(); f++)
737 faces[parent.faces(f)].add_element(parent_id);
739 for (
int e = 0; e < parent.edges.size(); e++)
740 edges[parent.edges(e)].add_element(parent_id);
742 for (
int v = 0; v < parent.vertices.size(); v++)
743 vertices[parent.vertices(v)].add_element(parent_id);
750 for (
auto &face :
faces)
752 if (face.n_elem() == 1)
753 face.isboundary =
true;
755 face.isboundary =
false;
758 for (
auto &face :
faces)
760 if (face.leader >= 0 && face.n_elem() > 0 &&
faces[face.leader].n_elem() > 0)
762 face.isboundary =
false;
763 faces[face.leader].isboundary =
false;
768 vert.isboundary =
false;
770 for (
auto &edge :
edges)
771 edge.isboundary =
false;
773 for (
auto &face :
faces)
775 if (face.isboundary && face.n_elem())
777 for (
int j = 0; j < 3; j++)
778 vertices[face.vertices(j)].isboundary =
true;
780 for (
int j = 0; j < 3; j++)
781 for (
int i = 0; i < j; i++)
782 edges[
find_edge(face.vertices(i), face.vertices(j))].isboundary =
true;
792 for (
int i = 0, e = 0; i <
elements.size(); i++)
806 for (
int i = 0, j = 0; i <
vertices.size(); i++)
818 for (
int i = 0, j = 0; i <
edges.size(); i++)
820 if (
edges[i].n_elem() == 0)
830 for (
int i = 0, j = 0; i <
faces.size(); i++)
832 if (
faces[i].n_elem() == 0)
843 assert(
typeid(mesh) ==
typeid(
NCMesh3D));
856 for (
int i = 0; i < mesh3d.
n_cells(); i++)
858 Eigen::Vector4i cell = mesh3d.
elements[i].vertices;
859 cell = cell.array() + n_v;
868 return std::make_unique<NCMesh3D>(*
this);
876 GEO::mesh_load(path, M);
883 assert(M.vertices.dimension() == 3);
885 Eigen::MatrixXd
V(M.vertices.nb(), 2);
886 Eigen::MatrixXi C(M.cells.nb(), 4);
888 for (
int v = 0; v <
V.rows(); v++)
889 V.row(v) << M.vertices.point(v)[0], M.vertices.point(v)[1], M.vertices.point(v)[2];
891 for (
int c = 0; c < C.rows(); c++)
893 if (M.cells.type(c) != GEO::MESH_TET)
894 throw std::runtime_error(
"NCMesh3D only supports tet mesh!");
895 for (
int i = 0; i < C.cols(); i++)
896 C(c, i) = M.cells.vertex(c, i);
901 for (
int i = 0; i <
V.rows(); i++)
905 for (
int i = 0; i < C.rows(); i++)
917 std::sort(v.data(), v.data() + v.size());
920 return search->second;
926 std::sort(v.data(), v.data() + v.size());
939 std::sort(v.data(), v.data() + v.size());
942 return search->second;
948 std::sort(v.data(), v.data() + v.size());
952 edges.emplace_back(v);
953 id =
edges.size() - 1;
960 std::sort(v.data(), v.data() + v.size());
963 return search->second;
969 std::sort(v.data(), v.data() + v.size());
973 faces.emplace_back(v);
974 id =
faces.size() - 1;
982 std::vector<follower_edge> list1, list2;
985 double p_mid = (p1 + p2) / 2;
986 traverse_edge(Eigen::Vector2i(v[0], v_mid), p1, p_mid, depth + 1, list1);
989 std::make_move_iterator(list1.begin()),
990 std::make_move_iterator(list1.end()));
991 traverse_edge(Eigen::Vector2i(v_mid, v[1]), p_mid, p2, depth + 1, list2);
994 std::make_move_iterator(list2.begin()),
995 std::make_move_iterator(list2.end()));
1000 if (follower_id >= 0 &&
edges[follower_id].n_elem() > 0)
1001 list.emplace_back(follower_id, p1, p2);
1006 for (
auto &edge :
edges)
1009 edge.followers.clear();
1010 edge.weights.setConstant(-1);
1013 for (
int e_id = 0; e_id <
edges.size(); e_id++)
1015 auto &edge =
edges[e_id];
1016 if (edge.n_elem() == 0)
1018 std::vector<follower_edge> followers;
1020 for (
auto &s : followers)
1022 if (
edges[s.id].leader >= 0 && std::abs(
edges[s.id].weights(1) -
edges[s.id].weights(0)) < std::abs(s.p2 - s.p1))
1024 edge.followers.push_back(s.id);
1025 edges[s.id].leader = e_id;
1026 edges[s.id].weights << s.p1, s.p2;
1031 for (
auto &edge :
edges)
1032 if (edge.leader >= 0 && edge.followers.size())
1033 edge.followers.clear();
1035 void NCMesh3D::traverse_face(
int v1,
int v2,
int v3, Eigen::Vector2d p1, Eigen::Vector2d p2, Eigen::Vector2d p3,
int depth, std::vector<follower_face> &face_list, std::vector<int> &edge_list)
const
1040 std::vector<follower_face> list1, list2, list3, list4;
1041 std::vector<int> list1_, list2_, list3_, list4_;
1048 if (v12 >= 0 && v23 >= 0 && v31 >= 0)
1050 auto p12 = (p1 + p2) / 2, p23 = (p2 + p3) / 2, p31 = (p1 + p3) / 2;
1051 traverse_face(v1, v12, v31, p1, p12, p31, depth + 1, list1, list1_);
1052 traverse_face(v12, v2, v23, p12, p2, p23, depth + 1, list2, list2_);
1053 traverse_face(v31, v23, v3, p31, p23, p3, depth + 1, list3, list3_);
1054 traverse_face(v12, v23, v31, p12, p23, p31, depth + 1, list4, list4_);
1056 face_list.insert(face_list.end(), std::make_move_iterator(list1.begin()), std::make_move_iterator(list1.end()));
1057 face_list.insert(face_list.end(), std::make_move_iterator(list2.begin()), std::make_move_iterator(list2.end()));
1058 face_list.insert(face_list.end(), std::make_move_iterator(list3.begin()), std::make_move_iterator(list3.end()));
1059 face_list.insert(face_list.end(), std::make_move_iterator(list4.begin()), std::make_move_iterator(list4.end()));
1061 edge_list.insert(edge_list.end(), std::make_move_iterator(list1_.begin()), std::make_move_iterator(list1_.end()));
1062 edge_list.insert(edge_list.end(), std::make_move_iterator(list2_.begin()), std::make_move_iterator(list2_.end()));
1063 edge_list.insert(edge_list.end(), std::make_move_iterator(list3_.begin()), std::make_move_iterator(list3_.end()));
1064 edge_list.insert(edge_list.end(), std::make_move_iterator(list4_.begin()), std::make_move_iterator(list4_.end()));
1068 int follower_id =
find_face(Eigen::Vector3i(v1, v2, v3));
1069 if (follower_id >= 0 &&
faces[follower_id].n_elem() > 0)
1070 face_list.emplace_back(follower_id, p1, p2, p3);
1075 Eigen::Matrix<int, 4, 3> fv;
1076 fv.row(0) << 0, 1, 2;
1077 fv.row(1) << 0, 1, 3;
1078 fv.row(2) << 1, 2, 3;
1079 fv.row(3) << 2, 0, 3;
1081 for (
auto &face :
faces)
1084 face.followers.clear();
1087 for (
auto &edge :
edges)
1089 edge.leader_face = -1;
1092 for (
int f_id = 0; f_id <
faces.size(); f_id++)
1094 auto &face =
faces[f_id];
1095 if (face.n_elem() == 0)
1097 std::vector<follower_face> followers;
1098 std::vector<int> interior_edges;
1099 traverse_face(face.vertices(0), face.vertices(1), face.vertices(2), Eigen::Vector2d(0, 0), Eigen::Vector2d(1, 0), Eigen::Vector2d(0, 1), 0, followers, interior_edges);
1100 for (
auto &s : followers)
1102 faces[s.id].leader = f_id;
1103 face.followers.push_back(s.id);
1105 for (
int s : interior_edges)
1106 if (s >= 0 &&
edges[s].leader < 0 &&
edges[s].n_elem() > 0)
1107 edges[s].leader_face = f_id;
1118 for (
auto &small_edge :
edges)
1121 if (small_edge.n_elem() == 0)
1125 int large_edge = small_edge.leader;
1128 assert(
edges[large_edge].leader < 0);
1131 for (
int j = 0; j < 2; j++)
1133 const int v_id = small_edge.vertices(j);
1140 for (
auto &small_face :
faces)
1143 if (small_face.n_elem() == 0)
1147 int large_face = small_face.leader;
1152 for (
int j = 0; j < 3; j++)
1154 const int v_id = small_face.vertices(j);
1156 if (v_id !=
faces[large_face].
vertices(0) && v_id !=
faces[large_face].vertices(1) && v_id !=
faces[large_face].vertices(2))
1168 const int level = (parent < 0) ? 0 :
elements[parent].level + 1;
1173 if ((e1.cross(e2)).dot(e3) < 0)
1174 std::swap(v[2], v[3]);
1178 assert((e1.cross(e2)).dot(e3) > 0);
1180 elements.emplace_back(3, v, level, parent);
1186 const int face012 =
get_face(v[0], v[1], v[2]);
1187 const int face013 =
get_face(v[0], v[1], v[3]);
1188 const int face123 =
get_face(v[1], v[2], v[3]);
1189 const int face203 =
get_face(v[2], v[0], v[3]);
1191 faces[face012].add_element(
id);
1192 faces[face013].add_element(
id);
1193 faces[face123].add_element(
id);
1194 faces[face203].add_element(
id);
1196 elements[id].faces << face012, face013, face123, face203;
1199 const int edge01 =
get_edge(v[0], v[1]);
1200 const int edge12 =
get_edge(v[1], v[2]);
1201 const int edge20 =
get_edge(v[2], v[0]);
1202 const int edge03 =
get_edge(v[0], v[3]);
1203 const int edge13 =
get_edge(v[1], v[3]);
1204 const int edge23 =
get_edge(v[2], v[3]);
1206 edges[edge01].add_element(
id);
1207 edges[edge12].add_element(
id);
1208 edges[edge20].add_element(
id);
1209 edges[edge03].add_element(
id);
1210 edges[edge13].add_element(
id);
1211 edges[edge23].add_element(
id);
1213 elements[id].edges << edge01, edge12, edge20, edge03, edge13, edge23;
1217 for (
int i = 0; i < v.size(); i++)
Abstract mesh class to capture 2d/3d conforming and non-conforming meshes.
std::vector< ElementType > elements_tag_
list of element types
bool has_boundary_ids() const
checks if surface selections are available
bool has_node_ids() const
checks if points selections are available
std::vector< int > boundary_ids_
list of surface labels
std::vector< int > node_ids_
list of node labels
std::vector< int > element_vertices(const int el_id) const
list of vids of an element
std::vector< int > body_ids_
list of volume labels
virtual int get_default_boundary_id(const int primitive) const
Get the default boundary selection of an element (face in 3d, edge in 2d)
void filter_element_data(const std::vector< bool > &keep)
virtual void append(const Mesh &mesh)
appends a new mesh to the end of this
void remove_elements(const std::vector< bool > &keep) override
Remove all top-dimensional elements whose mask entry is false.
int find_vertex(Eigen::Vector2i v) const
bool is_boundary_element(const int element_global_id) const override
is cell boundary
void compute_body_ids(const std::function< int(const size_t, const std::vector< int > &, const RowVectorNd &)> &marker) override
computes boundary selections based on a function
std::vector< int > all_to_valid_elemMap
int n_faces() const override
number of faces
int valid_to_all_edge(const int id) const
Navigation3D::Index next_around_edge(Navigation3D::Index idx) const override
int face_edge(const int f_id, const int le_id) const
int n_cell_faces(const int c_id) const override
void traverse_edge(Eigen::Vector2i v, double p1, double p2, int depth, std::vector< follower_edge > &list) const
std::unordered_map< Eigen::Vector2i, int, ArrayHasher2D > midpointMap
int n_cells() const override
number of cells
void build_element_vertex_adjacency()
void prepare_mesh() override
method used to finalize the mesh.
std::vector< ncBoundary > edges
int valid_to_all_face(const int id) const
void bounding_box(RowVectorNd &min, RowVectorNd &max) const override
computes the bbox of the mesh
void append(const Mesh &mesh) override
appends a new mesh to the end of this
std::vector< int > refineHistory
double edge_length(const int gid) const override
edge length
int n_edges() const override
number of edges
void compute_boundary_ids(const std::function< int(const size_t, const std::vector< int > &, const RowVectorNd &, bool)> &marker) override
computes boundary selections based on a function
int get_edge(Eigen::Vector2i v)
void set_point(const int global_index, const RowVectorNd &p) override
Set the point.
int add_element(Eigen::Vector4i v, int parent=-1)
int get_face(Eigen::Vector3i v)
void attach_higher_order_nodes(const Eigen::MatrixXd &V, const std::vector< std::vector< int > > &nodes) override
attach high order nodes
int n_face_vertices(const int f_id) const override
number of vertices of a face
RowVectorNd cell_barycenter(const int c) const override
cell barycenter
std::vector< uint32_t > edge_neighs(const int e_gid) const override
int all_to_valid_elem(const int id) const
int n_vertices() const override
number of vertices
std::vector< ncVert > vertices
Navigation3D::Index get_index_from_element_edge(int hi, int v0, int v1) const override
std::unordered_map< Eigen::Vector2i, int, ArrayHasher2D > edgeMap
void traverse_face(int v1, int v2, int v3, Eigen::Vector2d p1, Eigen::Vector2d p2, Eigen::Vector2d p3, int depth, std::vector< follower_face > &face_list, std::vector< int > &edge_list) const
void refine(const int n_refinement, const double t) override
refine the mesh
void normalize() override
normalize the mesh
std::vector< int > all_to_valid_vertexMap
int all_to_valid_edge(const int id) const
void get_face_elements_neighs(const int f_id, std::vector< int > &ids) const
std::unique_ptr< Mesh > copy() const override
Create a copy of the mesh.
int valid_to_all_elem(const int id) const
void refine_element(int id_full)
Navigation3D::Index switch_vertex(Navigation3D::Index idx) const override
RowVectorNd kernel(const int cell_id) const override
bool is_boundary_vertex(const int vertex_global_id) const override
is vertex boundary
int cell_face(const int c_id, const int lf_id) const override
bool build_from_matrices(const Eigen::MatrixXd &V, const Eigen::MatrixXi &F) override
build a mesh from matrices
void compute_elements_tag() override
compute element types, see ElementType
RowVectorNd point(const int global_index) const override
point coordinates
std::vector< int > all_to_valid_edgeMap
int find_edge(Eigen::Vector2i v) const
Navigation3D::Index get_index_from_element(int hi, int lf, int lv) const override
bool is_boundary_face(const int face_global_id) const override
is face boundary
int cell_vertex(const int f_id, const int lv_id) const override
id of the vertex of a cell
std::vector< int > all_to_valid_faceMap
void coarsen_element(int id_full)
Navigation3D::Index next_around_face(Navigation3D::Index idx) const override
std::vector< int > valid_to_all_elemMap
std::vector< int > valid_to_all_edgeMap
void build_face_follower_chain()
RowVectorNd face_barycenter(const int f) const override
face barycenter
void build_edge_follower_chain()
int n_cell_edges(const int c_id) const override
Navigation3D::Index switch_element(Navigation3D::Index idx) const override
void get_vertex_elements_neighs(const int v_id, std::vector< int > &ids) const override
std::vector< ncElem > elements
std::unordered_map< Eigen::Vector3i, int, ArrayHasher3D > faceMap
RowVectorNd edge_barycenter(const int e) const override
edge barycenter
std::vector< int > valid_to_all_faceMap
std::vector< uint32_t > vertex_neighs(const int v_gid) const override
std::vector< int > valid_to_all_vertexMap
std::array< int, 4 > get_ordered_vertices_from_tet(const int element_index) const override
void update_elements_tag() override
Update elements types.
int valid_to_all_vertex(const int id) const
int edge_vertex(const int e_id, const int lv_id) const override
id of the edge vertex
void refine_elements(const std::vector< int > &ids)
void build_index_mapping()
int get_vertex(Eigen::Vector2i v)
int find_face(Eigen::Vector3i v) const
void get_edge_elements_neighs(const int e_id, std::vector< int > &ids) const override
Navigation3D::Index switch_face(Navigation3D::Index idx) const override
int face_vertex(const int f_id, const int lv_id) const override
id of the face vertex
int all_to_valid_face(const int id) const
bool load(const std::string &path) override
loads a mesh from the path
Navigation3D::Index get_index_from_element_face(int hi, int v0, int v1, int v2) const override
void set_body_ids(const std::vector< int > &body_ids) override
Set the volume sections.
void set_boundary_ids(const std::vector< int > &boundary_ids) override
Set the boundary selection from a vector.
std::vector< ncBoundary > faces
Navigation3D::Index switch_edge(Navigation3D::Index idx) const override
bool endswith(const std::string &str, const std::string &suffix)
std::tuple< bool, int, Tree > is_valid(const int dim, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const Eigen::VectorXd &u, const double threshold, const unsigned max_iter)
Eigen::Matrix< double, 1, Eigen::Dynamic, Eigen::RowMajor, 1, 3 > RowVectorNd