32 for (
auto &coord : x) {
33 if (coord < 0.0) coord = 0.0;
34 if (coord > 1.0) coord = 1.0;
38 auto pgt_torus = std::dynamic_pointer_cast<const torus_geom_trans>(pgt);
40 orig_pgt = pgt_torus ? pgt_torus->get_original_transformation()
44 auto nb_simplices = pbasic_convex_ref->simplexified_convex()->nb_convex();
46 if (nb_simplices == 1) {
47 auto sum_coordinates = 0.0;
48 for (
const auto &coord : x) sum_coordinates += coord;
50 if (sum_coordinates > 1.0) gmm::scale(x, 1.0 / sum_coordinates);
52 else if (pgt->dim() == 3 && nb_simplices != 4) {
53 auto sum_coordinates = x[0] + x[1];
54 if (sum_coordinates > 1.0) {
55 x[0] /= sum_coordinates;
56 x[1] /= sum_coordinates;
63 bool project_into_element) {
64 bool converged =
true;
65 return invert(n, n_ref, converged, IN_EPS, project_into_element);
71 bool project_into_element) {
73 n_ref.resize(pgt->structure()->dim());
76 return invert_lin(n, n_ref, IN_EPS);
78 return invert_nonlin(n, n_ref, IN_EPS, converged,
false,
79 project_into_element);
86 mult(transposed(B), y, n_ref);
87 y = pgt->transform(n_ref, G);
88 add(gmm::scaled(n, -1.0), y);
90 return (pgt->convex_ref()->is_in(n_ref) < IN_EPS) &&
91 (gmm::vect_norm2(y) < IN_EPS);
94 void geotrans_inv_convex::update_B() {
96 pgt->compute_K_matrix(G, pc, K);
97 gmm::mult(gmm::transposed(K), K, CS);
98 bgeot::lu_inverse(&(*(CS.begin())), P);
104 base_matrix KT(K.nrows(), K.ncols());
105 pgt->compute_K_matrix(G, pc, KT);
106 gmm::copy(gmm::transposed(KT), K);
108 bgeot::lu_inverse(&(*(K.begin())), P); B.swap(K);
112 class geotrans_inv_convex_bfgs {
113 geotrans_inv_convex &gic;
116 geotrans_inv_convex_bfgs(geotrans_inv_convex &gic_,
117 const base_node &xr) : gic(gic_), xreal(xr) {}
118 scalar_type operator()(
const base_node& x)
const {
119 base_node r = gic.pgt->transform(x, gic.G) - xreal;
122 void operator()(
const base_node& x, base_small_vector& gr)
const {
123 gic.pgt->poly_vector_grad(x, gic.pc);
125 base_node r = gic.pgt->transform(x, gic.G) - xreal;
127 gmm::mult(gmm::transposed(gic.K), r, gr);
131 void geotrans_inv_convex::update_linearization() {
133 const convex_ind_ct &dir_pt_ind = pgt->structure()->ind_dir_points();
134 const stored_point_tab &ref_nodes = pgt->geometric_nodes();
136 has_linearized_approx =
true;
138 auto n_points = dir_pt_ind.size();
139 auto N_ref = ref_nodes.begin()->size();
141 std::vector<base_node> dir_pts, dir_pts_ref;
142 for (
auto i : dir_pt_ind) {
143 dir_pts.push_back(base_node(N));
144 gmm::copy(mat_col(G, i), dir_pts.back());
145 dir_pts_ref.push_back(ref_nodes[i]);
148 base_matrix K_lin(N, n_points - 1),
149 B_transp_lin(n_points - 1, N),
150 K_ref_lin(N_ref, n_points - 1);
153 P_ref_lin = dir_pts_ref[0];
155 for (
size_type i = 1; i < n_points; ++i) {
156 add(dir_pts[i], gmm::scaled(P_lin, -1.0), mat_col(K_lin, i - 1));
157 add(dir_pts_ref[i], gmm::scaled(P_ref_lin, -1.0),
158 mat_col(K_ref_lin, i - 1));
161 if (K_lin.nrows() == K_lin.ncols()) {
163 gmm::copy(K_lin, B_transp_lin);
166 base_matrix temp(n_points - 1, n_points - 1);
167 mult(transposed(K_lin), K_lin, temp);
169 mult(temp, transposed(K_lin), B_transp_lin);
172 K_ref_B_transp_lin.base_resize(N_ref, N);
173 mult(K_ref_lin, B_transp_lin, K_ref_B_transp_lin);
180 bool geotrans_inv_convex::invert_nonlin(
const base_node& xreal,
181 base_node& x, scalar_type IN_EPS,
184 bool project_into_element) {
186 base_node x0_ref(P), diff(N);
189 x0_ref = pgt->geometric_nodes()[0];
191 for (
size_type j = 1; j < pgt->nb_points(); ++j) {
195 x0_ref = pgt->geometric_nodes()[j];
199 scalar_type res0 = std::numeric_limits<scalar_type>::max();
200 if (has_linearized_approx) {
202 add(xreal, gmm::scaled(P_lin, -1.0), diff);
203 mult(K_ref_B_transp_lin, diff, x);
204 gmm::add(P_ref_lin, x);
206 if (project_into_element) project_into_convex(x, pgt);
210 if (res < res0) gmm::copy(x0_ref, x);
215 add(pgt->transform(x, G), gmm::scaled(xreal, -1.0), diff);
217 scalar_type res0 = std::numeric_limits<scalar_type>::max();
218 scalar_type factor = 1.0;
220 base_node x0_real(N);
221 while (res > IN_EPS/100.) {
222 if ((gmm::abs(res - res0) < IN_EPS/100.) || (factor < IN_EPS)) {
224 return (pgt->convex_ref()->is_in(x) < IN_EPS) && (res < IN_EPS);
227 add(gmm::scaled(x0_ref, factor), x);
228 x0_real = pgt->transform(x, G);
229 add(x0_real, gmm::scaled(xreal, -1.0), diff);
233 if (factor < 1.0-IN_EPS) factor *= 2.0;
236 pgt->poly_vector_grad(x, pc);
238 mult(transposed(B), diff, x0_ref);
239 add(gmm::scaled(x0_ref, -factor), x);
240 if (project_into_element) project_into_convex(x, pgt);
241 x0_real = pgt->transform(x, G);
242 add(x0_real, gmm::scaled(xreal, -1.0), diff);
245 return (pgt->convex_ref()->is_in(x) < IN_EPS) && (res < IN_EPS);