31 for (
auto &coord : x) {
32 if (coord < 0.0) coord = 0.0;
33 if (coord > 1.0) coord = 1.0;
37 auto pgt_torus = std::dynamic_pointer_cast<const torus_geom_trans>(pgt);
39 orig_pgt = pgt_torus ? pgt_torus->get_original_transformation()
43 auto nb_simplices = pbasic_convex_ref->simplexified_convex()->nb_convex();
45 if (nb_simplices == 1) {
46 auto sum_coordinates = 0.0;
47 for (
const auto &coord : x) sum_coordinates += coord;
49 if (sum_coordinates > 1.0) gmm::scale(x, 1.0 / sum_coordinates);
51 else if (pgt->dim() == 3 && nb_simplices != 4) {
52 auto sum_coordinates = x[0] + x[1];
53 if (sum_coordinates > 1.0) {
54 x[0] /= sum_coordinates;
55 x[1] /= sum_coordinates;
62 bool project_into_element) {
63 bool converged =
true;
64 return invert(n, n_ref, converged, IN_EPS, project_into_element);
70 bool project_into_element) {
72 n_ref.resize(pgt->structure()->dim());
75 return invert_lin(n, n_ref, IN_EPS);
77 return invert_nonlin(n, n_ref, IN_EPS, converged,
false,
78 project_into_element);
85 mult(transposed(B), y, n_ref);
86 y = pgt->transform(n_ref, G);
87 add(gmm::scaled(n, -1.0), y);
89 return (pgt->convex_ref()->is_in(n_ref) < IN_EPS) &&
90 (gmm::vect_norm2(y) < IN_EPS);
93 bool geotrans_inv_convex::update_B() {
95 pgt->compute_K_matrix(G, pc, K);
96 gmm::mult(gmm::transposed(K), K, CS);
97 double det = bgeot::lu_inverse(&(*(CS.begin())), P,
false);
104 base_matrix KT(K.nrows(), K.ncols());
105 pgt->compute_K_matrix(G, pc, KT);
108 double det = bgeot::lu_inverse(&(*(K.begin())), P,
false);
116 class geotrans_inv_convex_bfgs {
117 geotrans_inv_convex &gic;
120 geotrans_inv_convex_bfgs(geotrans_inv_convex &gic_,
121 const base_node &xr) : gic(gic_), xreal(xr) {}
122 scalar_type operator()(
const base_node& x)
const {
123 base_node r = gic.pgt->transform(x, gic.G) - xreal;
126 void operator()(
const base_node& x, base_small_vector& gr)
const {
127 gic.pgt->poly_vector_grad(x, gic.pc);
129 base_node r = gic.pgt->transform(x, gic.G) - xreal;
131 gmm::mult(gmm::transposed(gic.K), r, gr);
135 void geotrans_inv_convex::update_linearization() {
137 const convex_ind_ct &dir_pt_ind = pgt->structure()->ind_dir_points();
138 const stored_point_tab &ref_nodes = pgt->geometric_nodes();
140 has_linearized_approx =
true;
142 auto n_points = dir_pt_ind.size();
143 auto N_ref = ref_nodes.begin()->size();
145 std::vector<base_node> dir_pts, dir_pts_ref;
146 for (
auto i : dir_pt_ind) {
147 dir_pts.push_back(base_node(N));
148 gmm::copy(mat_col(G, i), dir_pts.back());
149 dir_pts_ref.push_back(ref_nodes[i]);
152 base_matrix K_lin(N, n_points - 1),
153 B_transp_lin(n_points - 1, N),
154 K_ref_lin(N_ref, n_points - 1);
157 P_ref_lin = dir_pts_ref[0];
159 for (
size_type i = 1; i < n_points; ++i) {
160 add(dir_pts[i], gmm::scaled(P_lin, -1.0), mat_col(K_lin, i - 1));
161 add(dir_pts_ref[i], gmm::scaled(P_ref_lin, -1.0),
162 mat_col(K_ref_lin, i - 1));
165 if (K_lin.nrows() == K_lin.ncols()) {
170 base_matrix temp(n_points - 1, n_points - 1);
171 mult(transposed(K_lin), K_lin, temp);
173 mult(temp, transposed(K_lin), B_transp_lin);
176 K_ref_B_transp_lin.base_resize(N_ref, N);
177 mult(K_ref_lin, B_transp_lin, K_ref_B_transp_lin);
184 bool geotrans_inv_convex::invert_nonlin(
const base_node& xreal,
189 bool project_into_element) {
191 base_node x0_ref(P), x0_real(N), diff(N);
194 x0_ref = pgt->geometric_nodes()[0];
196 for (
size_type j = 1; j < pgt->nb_points(); ++j) {
200 x0_ref = pgt->geometric_nodes()[j];
203 if (res < maxnormG * IN_EPS/100.) {
205 if (project_into_element) project_into_convex(xref, pgt);
206 x0_real = pgt->transform(xref, G);
207 add(x0_real, gmm::scaled(xreal, -1.0), diff);
209 if (res < maxnormG * IN_EPS/100. &&
210 pgt->convex_ref()->is_in(xref) < IN_EPS) {
216 scalar_type res0 = std::numeric_limits<scalar_type>::max();
217 if (has_linearized_approx) {
219 add(xreal, gmm::scaled(P_lin, -1.0), diff);
220 mult(K_ref_B_transp_lin, diff, xref);
223 if (project_into_element) project_into_convex(xref, pgt);
232 add(pgt->transform(xref, G), gmm::scaled(xreal, -1.0), diff);
234 scalar_type res0 = std::numeric_limits<scalar_type>::max();
235 scalar_type factor = 1.0;
237 while (res >= maxnormG * IN_EPS/100.) {
238 if ((gmm::abs(res - res0) < IN_EPS/100.) || (factor < IN_EPS)) {
241 converged = (res < maxnormG * IN_EPS/100.);
242 return converged && (pgt->convex_ref()->is_in(xref) < IN_EPS);
245 add(gmm::scaled(x0_ref, factor), xref);
246 x0_real = pgt->transform(xref, G);
247 add(x0_real, gmm::scaled(xreal, -1.0), diff);
250 if (factor < 1.0-IN_EPS) factor *= 2.0;
253 pgt->poly_vector_grad(xref, pc);
258 mult(transposed(B), diff, x0_ref);
259 add(gmm::scaled(x0_ref, -factor), xref);
260 if (project_into_element) project_into_convex(xref, pgt);
261 x0_real = pgt->transform(xref, G);
262 add(x0_real, gmm::scaled(xreal, -1.0), diff);
266 return (pgt->convex_ref()->is_in(xref) < 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.