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);
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()) {
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);
206 if (project_into_element) project_into_convex(x, pgt);
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)) {
226 return (pgt->convex_ref()->is_in(x) < IN_EPS) && (res < IN_EPS);
229 add(gmm::scaled(x0_ref, factor), x);
230 x0_real = pgt->transform(x, G);
231 add(x0_real, gmm::scaled(xreal, -1.0), diff);
235 if (factor < 1.0-IN_EPS) factor *= 2.0;
238 pgt->poly_vector_grad(x, pc);
240 mult(transposed(B), diff, x0_ref);
241 add(gmm::scaled(x0_ref, -factor), x);
242 if (project_into_element) project_into_convex(x, pgt);
243 x0_real = pgt->transform(x, G);
244 add(x0_real, gmm::scaled(xreal, -1.0), diff);
247 return (pgt->convex_ref()->is_in(x) < IN_EPS) && (res < IN_EPS);
Inversion of geometric transformations.
Mesh structure definition.
bool invert(const base_node &n, base_node &n_ref, scalar_type IN_EPS=1e-12, bool project_into_element=false)
given the node on the real element, returns the node on the reference element (even if it is outside ...
void copy(const L1 &l1, L2 &l2)
*/
number_traits< typename linalg_traits< V >::value_type >::magnitude_type vect_norm2(const V &v)
Euclidean norm of a vector.
number_traits< typename linalg_traits< M >::value_type >::magnitude_type mat_maxnorm(const M &m)
*/
number_traits< typename linalg_traits< V >::value_type >::magnitude_type vect_norm2_sqr(const V &v)
squared Euclidean norm of a vector.
number_traits< typename linalg_traits< V1 >::value_type >::magnitude_type vect_dist2(const V1 &v1, const V2 &v2)
Euclidean distance between two vectors.
void mult(const L1 &l1, const L2 &l2, L3 &l3)
*/
void add(const L1 &l1, L2 &l2)
*/
Implements BFGS (Broyden, Fletcher, Goldfarb, Shanno) algorithm.
size_t size_type
used as the common size type in the library
std::shared_ptr< const bgeot::geometric_trans > pgeometric_trans
pointer type for a geometric transformation
pconvex_ref basic_convex_ref(pconvex_ref cvr)
return the associated order 1 reference convex.