11 *iface =
const_cast<Tools *
>(
this);
17 for (
int dd = 0;
dd != 3;
dd++) {
18 lrms += pow(coords[0 * 3 +
dd] - coords[1 * 3 +
dd], 2) +
19 pow(coords[0 * 3 +
dd] - coords[2 * 3 +
dd], 2) +
20 pow(coords[0 * 3 +
dd] - coords[3 * 3 +
dd], 2) +
21 pow(coords[1 * 3 +
dd] - coords[2 * 3 +
dd], 2) +
22 pow(coords[1 * 3 +
dd] - coords[3 * 3 +
dd], 2) +
23 pow(coords[2 * 3 +
dd] - coords[3 * 3 +
dd], 2);
25 lrms = sqrt((1. / 6.) * lrms);
27 return 6. * sqrt(2.) * volume / pow(lrms, 3);
40 for (
int nn = 0; nn != 4; nn++) {
41 jac(
i,
j) += t_coords(
i) * t_diff_n(
j);
50 boost::function<
double(
double,
double)>
f) {
57 for (
auto tet : tets) {
58 CHKERR m_field.
get_moab().get_connectivity(tet, conn, num_nodes,
true);
60 CHKERR moab.tag_get_data(
th, conn, num_nodes, coords);
62 CHKERR moab.get_coords(conn, num_nodes, coords);
65 if (!std::isnormal(q))
67 min_quality =
f(q, min_quality);
89 const double *elem_coords,
const double *global_coords,
const int nb_nodes,
90 double *local_coords) {
95 &elem_coords[0], &elem_coords[3], &elem_coords[6], &elem_coords[9]};
106 for (
auto ii : {0, 1, 2}) {
110 for (
auto jj : {0, 1, 2}) {
111 a(jj, ii) = t_diff(
i) * t_elem_coords(
i);
114 t_coords_at_0(ii) = t_n(
i) * t_elem_coords(
i);
119 &global_coords[0], &global_coords[1], &global_coords[2]};
121 &local_coords[0], &local_coords[1], &local_coords[2]};
125 for (
int ii = 0; ii != nb_nodes; ++ii) {
126 t_local_coords(
j) = t_global_coords(
j) - t_coords_at_0(
j);
133 int info =
lapack_dgesv(3, nb_nodes, &
a(0, 0), 3, IPIV, local_coords, 3);
135 SETERRQ1(PETSC_COMM_SELF, 1,
"info == %d", info);
140 template <
typename T1,
typename T2>
142 const T1 *elem_coords,
const T2 *global_coords,
const int nb_nodes,
154 auto t_diff = getFTensor2FromPtr<3, 2>(
156 auto t_elem_coords = getFTensor2FromPtr<3, 3>(
const_cast<T1 *
>(elem_coords));
160 t_a(K2, i3) = t_diff(j3, K2) * t_elem_coords(j3, i3);
162 t_b(K2,
L2) = t_a(K2, j3) ^ t_a(
L2, j3);
164 const auto inv_det = 1. / (t_b(0, 0) * t_b(1, 1) - t_b(0, 1) * t_b(1, 0));
165 t_inv_b(0, 0) = t_b(1, 1) * inv_det;
166 t_inv_b(0, 1) = -t_b(0, 1) * inv_det;
167 t_inv_b(1, 1) = t_b(0, 0) * inv_det;
171 t_coords_at_0(i3) = t_n(j3) * t_elem_coords(j3, i3);
173 auto t_global_coords = getFTensor1FromPtr<3>(
const_cast<T2 *
>(global_coords));
174 auto t_local_coords = getFTensor1FromPtr<2>(local_coords);
177 for (
int ii = 0; ii != nb_nodes; ++ii) {
180 (t_a(K2, j3) * (t_global_coords(j3) - t_coords_at_0(j3)));
189 const double *elem_coords,
const double *glob_coords,
const int nb_nodes,
190 double *local_coords) {
191 return getLocalCoordinatesOnReferenceThreeNodeTriImpl<double, double>(
192 elem_coords, glob_coords, nb_nodes, local_coords);
196 const double *elem_coords,
const std::complex<double> *glob_coords,
197 const int nb_nodes, std::complex<double> *local_coords) {
199 std::complex<double>>(
200 elem_coords, glob_coords, nb_nodes, local_coords);
204 const double *elem_coords,
const double *global_coords,
const int nb_nodes,
205 double *local_coords) {
211 &elem_coords[0], &elem_coords[3], &elem_coords[6]};
217 for (
auto ii : {0, 1, 2}) {
226 &global_coords[0], &global_coords[1], &global_coords[2]};
230 const double b = t_a(i3) * t_a(i3);
231 const double inv_b = 1 / b;
234 for (
int ii = 0; ii != nb_nodes; ++ii) {
236 inv_b * (t_a(i3) * (t_global_coords(i3) - t_coords_at_0(i3)));
246 boost::function<
bool(
double)>
f) {
254 for (
auto tet : tets) {
255 CHKERR m_field.
get_moab().get_connectivity(tet, conn, num_nodes,
true);
257 CHKERR moab.tag_get_data(
th, conn, num_nodes, coords);
259 CHKERR moab.get_coords(conn, num_nodes, coords);
263 out_tets.insert(tet);
270 const char *file_type,
273 boost::function<
bool(
double)>
f) {
280 CHKERR moab.create_meshset(MESHSET_SET, meshset);
281 CHKERR moab.add_entities(meshset, out_tets);
282 CHKERR moab.write_file(file_name, file_type, options, &meshset, 1);
283 CHKERR moab.delete_entities(&meshset, 1);
288 const double global_coord[],
289 const double tol,
bool &result) {
290 double loc_coord[] = {0, 0, 0};
291 double N[4], diffN[12];
298 for (
int n = 0;
n != 4; ++
n) {
312 CHKERR VecGetLocalSize(
v, &loc_size);
313 int prb_loc_size = 0;
314 boost::shared_ptr<NumeredDofEntity_multiIndex> prb_dofs;
315 switch (row_or_col) {
327 "Wrong argument, row_or_col should be row or column");
329 if (loc_size != prb_loc_size) {
331 "Inconsistent size of vector and problem %d != %d", loc_size,
336 MPI_Comm comm = PetscObjectComm((PetscObject)
v);
337 for (
int ii = 0; ii != loc_size; ++ii) {
338 if (!boost::math::isfinite(
a[ii])) {
339 NumeredDofEntityByLocalIdx::iterator dit =
341 std::ostringstream ss;
342 ss <<
"Not a number " <<
a[ii] <<
" on dof: " << endl
345 PetscSynchronizedPrintf(comm,
"%s", ss.str().c_str());
349 PetscSynchronizedFlush(comm, PETSC_STDOUT);
366 auto t_diff_tensor = getFTensor2FromPtr<3, 2>(
const_cast<double *
>(diff_ptr));
367 auto t_coords = getFTensor2FromPtr<3, 3>(
const_cast<double *
>(coords));
369 t_tangent(
i,
J) = t_coords(
n,
i) * t_diff_tensor(
n,
J);
370 auto t_normal = getFTensor1FromPtr<3>(normal);
378 t_d_tangent(
i,
k,
l,
J) = t_d_coords(
n,
i,
k,
l) * t_diff_tensor(
n,
J);
381 t_d_tangent(
k,
m,
n, N0)
386 t_d_tangent(
i,
m,
n, N1);
392 double *normal)
const {
402 CHKERR moab.get_connectivity(tri, conn, num_nodes,
true);
403 CHKERR moab.get_coords(conn, num_nodes, coords);
412 return sqrt(t_normal(
i) * t_normal(
i)) * 0.5;
421 t_coords_n0(
i) -= t_coords_n1(
i);
422 return sqrt(t_coords_n0(
i) * t_coords_n0(
i));
428 auto get_edge_coords = [edge, &moab](
double *
const coords) {
435 CHKERR moab.get_connectivity(edge, conn, num_nodes,
true);
436 CHKERR moab.get_coords(conn, 2, coords);
440 ierr = get_edge_coords(coords);
441 CHKERRABORT(PETSC_COMM_SELF,
ierr);
447 const double *p_ptr,
double *
const t_ptr) {
453 t_vw(
i) = t_v(
i) - t_w(
i);
454 const double dot_vw = t_vw(
i) * t_vw(
i);
455 if (std::abs(dot_vw) < std::numeric_limits<double>::epsilon()) {
461 t_pw(
i) = t_p(
i) - t_w(
i);
462 const double t = t_pw(
i) * t_vw(
i) / dot_vw;
470 const double *k_ptr,
const double *l_ptr,
471 double *
const tvw_ptr,
double *
const tlk_ptr) {
481 t_vw(
i) = t_v(
i) - t_w(
i);
482 double dot_vw = t_vw(
i) * t_vw(
i);
483 if (std::abs(dot_vw) < std::numeric_limits<double>::epsilon()) {
495 t_lk(
i) = t_l(
i) - t_k(
i);
496 double dot_lk = t_lk(
i) * t_lk(
i);
497 if (std::abs(dot_lk) < std::numeric_limits<double>::epsilon()) {
507 const double a = t_vw(
i) * t_vw(
i);
508 const double b = -t_vw(
i) * t_lk(
i);
509 const double c = t_lk(
i) * t_lk(
i);
511 const double det =
a *
c - b * b;
512 if (std::abs(det) < std::numeric_limits<double>::epsilon()) {
519 t_wk(
i) = t_w(
i) - t_k(
i);
521 const double ft0 = t_vw(
i) * t_wk(
i);
522 const double ft1 = -t_lk(
i) * t_wk(
i);
523 const double t0 = (ft1 * b - ft0 *
c) / det;
524 const double t1 = (ft0 * b - ft1 *
a) / det;
536 const double *v_ptr,
const int nb,
Range edges,
double *min_dist_ptr,
544 auto get_point = [
i](
auto &t_w,
auto &t_delta,
auto t) {
546 t = std::max(0., std::min(1.,
t));
547 t_p(
i) = t_w(
i) +
t * t_delta(
i);
551 auto get_distance = [
i](
auto &t_p,
auto &t_n) {
553 t_dist_vector(
i) = t_p(
i) - t_n(
i);
554 return sqrt(t_dist_vector(
i) * t_dist_vector(
i));
557 for (
auto e : edges) {
561 CHKERR moab.get_connectivity(e, conn_fixed, num_nodes,
true);
563 CHKERR moab.get_coords(conn_fixed, num_nodes, &coords_fixed[0]);
565 &coords_fixed[0], &coords_fixed[1], &coords_fixed[2]);
567 &coords_fixed[3], &coords_fixed[4], &coords_fixed[5]);
570 t_edge_delta(
i) = t_f1(
i) - t_f0(
i);
573 v_ptr, v_ptr + 1, v_ptr + 2);
575 o_ptr, o_ptr + 1, o_ptr + 2);
580 colsest_segment_it = o_segments;
582 for (
int n = 0;
n != nb; ++
n) {
587 auto t_p = get_point(t_f0, t_edge_delta,
t);
588 auto dist_n = get_distance(t_p, t_n);
589 if (dist_n < t_min_dist || t_min_dist < 0) {
592 t_min_coords(
i) = t_p(
i);
594 *colsest_segment_it = e;
603 ++colsest_segment_it;
611 MatrixDouble &gauss_pts,
const int rule_ksi,
const int rule_eta) {
614 auto check_rule_edge = [](
int rule) {
618 "Wrong integration rule: %d", rule);
634 CHKERR check_rule_edge(rule_ksi);
635 CHKERR check_rule_edge(rule_eta);
639 gauss_pts.resize(3, nb_gauss_pts_ksi * nb_gauss_pts_eta,
false);
642 for (
size_t i = 0;
i != nb_gauss_pts_ksi; ++
i) {
645 for (
size_t j = 0;
j != nb_gauss_pts_eta; ++
j, ++gg) {
648 gauss_pts(0, gg) = ksi;
649 gauss_pts(1, gg) =
eta;
650 gauss_pts(2, gg) = wk;
653 if (gg != gauss_pts.size2())
660 MatrixDouble &gauss_pts,
const int rule_ksi,
const int rule_eta,
661 const int rule_zeta) {
664 auto check_rule_edge = [](
int rule) {
668 "Wrong integration rule: %d", rule);
684 CHKERR check_rule_edge(rule_ksi);
685 CHKERR check_rule_edge(rule_eta);
686 CHKERR check_rule_edge(rule_zeta);
691 gauss_pts.resize(4, nb_gauss_pts_ksi * nb_gauss_pts_eta * nb_gauss_pts_zeta,
695 for (
size_t i = 0;
i != nb_gauss_pts_ksi; ++
i) {
698 for (
size_t j = 0;
j != nb_gauss_pts_eta; ++
j) {
701 for (
size_t k = 0;
k != nb_gauss_pts_zeta; ++
k, ++gg) {
704 gauss_pts(0, gg) = ksi;
705 gauss_pts(1, gg) =
eta;
706 gauss_pts(2, gg) =
zeta;
707 gauss_pts(3, gg) = wk;
712 if (gg != gauss_pts.size2())
720 std::tuple<std::vector<double>, std::vector<int>, std::vector<int>>
723 std::vector<int> triangles{0, 1, 2, 3, 4, 5};
724 std::vector<double> nodes{
734 std::map<std::pair<int, int>,
int> edges{
735 {{0, 1}, 3}, {{1, 2}, 4}, {{0, 2}, 5}};
737 auto add_edge = [&](
auto a,
auto b) {
741 auto it = edges.find(std::make_pair(
a, b));
742 if (it == edges.end()) {
743 int e = 3 + edges.size();
744 edges[std::make_pair(
a, b)] = e;
745 for (
auto n : {0, 1}) {
746 nodes.push_back((nodes[2 *
a +
n] + nodes[2 * b +
n]) / 2);
749 if (e != nodes.size() / 2 - 1)
757 auto add_triangle = [&](
auto t) {
758 for (
auto tt : {0, 1, 2, 3}) {
759 auto last = triangles.size() / 6;
760 for (
auto n : {0, 1, 2}) {
766 auto cycle = std::array<int, 4>{0, 1, 2, 0};
767 for (
auto e : {0, 1, 2}) {
768 triangles.push_back(add_edge(triangles[6 * last + cycle[e]],
769 triangles[6 * last + cycle[e + 1]]));
774 std::vector<int> level_index{0, 1};
777 auto first_tet = level_index[
l];
778 auto nb_last_level_test = level_index.back() - level_index[
l];
779 for (
auto t = first_tet;
t != (first_tet + nb_last_level_test); ++
t) {
782 level_index.push_back(triangles.size() / 6);
785 return std::make_tuple(nodes, triangles, level_index);
790 std::tuple<std::vector<double>, std::vector<int>, std::vector<int>>
793 auto [nodes, triangles, level_index] = refined;
795 auto get_coords = [&](
auto t) {
796 auto [nodes, triangles, level_index] = refined;
797 std::array<double, 9> ele_coords;
798 for (
auto n : {0, 1, 2}) {
799 for (
auto i : {0, 1}) {
800 ele_coords[3 *
n +
i] = nodes[2 * triangles[6 *
t +
n] +
i];
802 ele_coords[3 *
n + 2] = 0;
807 auto get_normal = [](
auto &ele_coords) {
813 std::vector<double> ele_shape(3 * pts.size2());
814 shapeFunMBTRI<1>(&*ele_shape.begin(), &pts(0, 0), &pts(1, 0), pts.size2());
816 int nb_elems = level_index.back() - level_index[level_index.size() - 2];
823 for (
auto t = level_index[level_index.size() - 2];
t != level_index.back();
826 auto ele_coords = get_coords(
t);
827 auto t_normal = get_normal(ele_coords);
828 auto area = t_normal.
l2();
831 &ele_shape[0], &ele_shape[1], &ele_shape[2]};
833 ele_coords[3], ele_coords[4],
834 ele_coords[6], ele_coords[7]};
839 for (
auto gg = 0; gg != pts.size2(); ++gg) {
840 t_gauss_pt(
J) = t_ele_shape(
i) * t_ele_coords(
i,
J);
841 t_gauss_weight = area * pts(2, gg);
858 gauss_pts.resize(3, nb_gauss_pts,
false);
859 cblas_dcopy(nb_gauss_pts, &
QUAD_2D_TABLE[rule]->points[1], 3,
860 &gauss_pts(0, 0), 1);
861 cblas_dcopy(nb_gauss_pts, &
QUAD_2D_TABLE[rule]->points[2], 3,
862 &gauss_pts(1, 0), 1);
863 cblas_dcopy(nb_gauss_pts,
QUAD_2D_TABLE[rule]->weights, 1, &gauss_pts(2, 0),