16 #include "proj_based_selector.h"
17 #include "hcurl_proj_based_selector.h"
19 #include "order_permutator.h"
20 #include "algebra/dense_matrix_operations.h"
28 namespace RefinementSelectors
30 template<
typename Scalar>
32 max_order,
Shapeset* shapeset,
const Range& vertex_order,
const
33 Range& edge_bubble_order) :
34 OptimumSelector<Scalar>(cand_list, max_order, shapeset, vertex_order, edge_bubble_order),
35 warn_uniform_orders(false),
50 for (
int k = 0; k < H2DRS_MAX_ORDER + 2; k++)
54 template<
typename Scalar>
61 for (
int k = 0; k < H2DRS_MAX_ORDER + 2; k++)
63 if (proj_matrix_cache[m][i][k] !=
nullptr)
64 free_with_check<double*>(proj_matrix_cache[m][i][k],
true);
68 delete[] cached_shape_vals_valid;
69 delete[] cached_shape_ortho_vals;
70 delete[] cached_shape_vals;
73 template<
typename Scalar>
76 error_weight_h = weight_h;
77 error_weight_p = weight_p;
78 error_weight_aniso = weight_aniso;
81 template<
typename Scalar>
84 return error_weight_h;
87 template<
typename Scalar>
88 double ProjBasedSelector<Scalar>::get_error_weight_p()
const
90 return error_weight_p;
93 template<
typename Scalar>
94 double ProjBasedSelector<Scalar>::get_error_weight_aniso()
const
96 return error_weight_aniso;
99 template<
typename Scalar>
102 template<
typename Scalar>
105 free_with_check(values,
true);
108 template<
typename Scalar>
111 free_with_check(values,
true);
112 values = new_matrix<double>(num_expansion, num_gip);
113 this->num_expansion = num_expansion;
114 this->num_gip = num_gip;
117 template<
typename Scalar>
120 return values[inx_expansion];
123 template<
typename Scalar>
124 bool ProjBasedSelector<Scalar>::TrfShapeExp::empty()
const
126 return values ==
nullptr;
129 template<
typename Scalar>
132 bool tri = e->is_triangle();
143 for (
unsigned i = 0; i < candidates.size(); i++)
145 Cand& c = candidates[i];
146 double error_squared = 0.0;
156 c.
errors[j] = herr[j][order][order];
157 error_squared += c.
errors[j];
160 error_squared *= 0.25;
166 c.
errors[0] = perr[order][order];
167 error_squared = perr[order][order];
172 throw Hermes::Exceptions::Exception(
"Unknown split type \"%d\" at candidate %d", c.
split, i);
185 c.
errors[j] = herr[j][order_h][order_v];
186 error_squared += c.
errors[j];
189 error_squared *= 0.25;
196 for (
int j = 0; j < 2; j++)
199 error_squared += c.
errors[j];
202 error_squared *= 0.5;
209 c.
errors[0] = perr[order_h][order_v];
210 error_squared = c.
errors[0];
215 throw Hermes::Exceptions::Exception(
"Unknown split type \"%d\" at candidate %d", c.
split, i);
220 c.
error = sqrt(error_squared);
229 default:
throw Hermes::Exceptions::Exception(
"Unknown split type \"%d\" at candidate %d", c.
split, i);
234 template<
typename Scalar>
240 Quad2D* quad = &g_quad_2d_std;
249 if (rsln_sln !=
nullptr)
282 int num_noni_trfs = 0;
283 if (mode == HERMES_MODE_TRIANGLE)
286 num_noni_trfs = H2D_TRF_TRI_NUM;
291 num_noni_trfs = H2D_TRF_QUAD_NUM;
299 #pragma omp critical (cached_shape_vals_valid)
321 #pragma region candidatesEvaluation
327 Trf* sub_trfs[4] = { &trfs[0], &trfs[1], &trfs[2], &trfs[3] };
328 std::vector<TrfShapeExp>* p_trf_svals[4] = { &svals[0], &svals[1], &svals[2], &svals[3] };
329 std::vector<TrfShapeExp>* p_trf_ortho_svals[4] = { &ortho_svals[0], &ortho_svals[1], &ortho_svals[2], &ortho_svals[3] };
332 int sub_rval[1] = { son };
334 , 1, &base_element, &sub_trfs[son], sub_rval
335 , &p_trf_svals[son], &p_trf_ortho_svals[son]
336 , info_h, herr[son], rval);
341 Trf* p_trf_identity[1] = { &trfs[H2D_TRF_IDENTITY] };
342 std::vector<TrfShapeExp>* p_trf_svals[1] = { &svals[H2D_TRF_IDENTITY] };
343 std::vector<TrfShapeExp>* p_trf_ortho_svals[1] = { &ortho_svals[H2D_TRF_IDENTITY] };
346 int sub_rval[1] = { son };
348 , 1, &base_element->
sons[son], p_trf_identity, sub_rval
349 , p_trf_svals, p_trf_ortho_svals
350 , info_h, herr[son], rval);
360 const int tr[4][2] = { { 0, 1 }, { 3, 2 }, { 0, 3 }, { 1, 2 } };
361 for (
int version = 0; version < 4; version++)
363 Trf* sub_trfs[2] = { &trfs[tr[version][0]], &trfs[tr[version][1]] };
364 Element* sub_domains[2] = { base_element, base_element };
365 int sub_rval[2] = { tr[version][0], tr[version][1] };
366 std::vector<TrfShapeExp>* sub_svals[2] = { &svals[tr[version][0]], &svals[tr[version][1]] };
367 std::vector<TrfShapeExp>* sub_ortho_svals[2] = { &ortho_svals[tr[version][0]], &ortho_svals[tr[version][1]] };
369 , 2, sub_domains, sub_trfs, sub_rval
370 , sub_svals, sub_ortho_svals
371 , info_aniso, anisoerr[version], rval);
377 const int sons[4][2] = { { 0, 1 }, { 3, 2 }, { 0, 3 }, { 1, 2 } };
379 const int tr[4][2] = { { 6, 7 }, { 6, 7 }, { 4, 5 }, { 4, 5 } };
380 for (
int version = 0; version < 4; version++)
382 Trf* sub_trfs[2] = { &trfs[tr[version][0]], &trfs[tr[version][1]] };
383 Element* sub_domains[2] = { base_element->
sons[sons[version][0]], base_element->
sons[sons[version][1]] };
384 int sub_rval[2] = { sons[version][0], sons[version][1] };
385 std::vector<TrfShapeExp>* sub_svals[2] = { &svals[tr[version][0]], &svals[tr[version][1]] };
386 std::vector<TrfShapeExp>* sub_ortho_svals[2] = { &ortho_svals[tr[version][0]], &ortho_svals[tr[version][1]] };
388 , 2, sub_domains, sub_trfs, sub_rval
389 , sub_svals, sub_ortho_svals
390 , info_aniso, anisoerr[version], rval);
400 Trf* sub_trfs[4] = { &trfs[0], &trfs[1], &trfs[2], &trfs[3] };
401 int sub_rval[4] = { 0, 1, 2, 3 };
402 std::vector<TrfShapeExp>* sub_svals[4] = { &svals[0], &svals[1], &svals[2], &svals[3] };
403 std::vector<TrfShapeExp>* sub_ortho_svals[4] = { &ortho_svals[0], &ortho_svals[1], &ortho_svals[2], &ortho_svals[3] };
404 Element* sub_domains[4] = { base_element, base_element, base_element, base_element };
407 , 4, sub_domains, sub_trfs, sub_rval
408 , sub_svals, sub_ortho_svals
409 , info_p, perr, rval);
413 Trf* sub_trfs[4] = { &trfs[0], &trfs[1], &trfs[2], &trfs[3] };
414 int sub_rval[4] = { 0, 1, 2, 3 };
415 std::vector<TrfShapeExp>* sub_svals[4] = { &svals[0], &svals[1], &svals[2], &svals[3] };
416 std::vector<TrfShapeExp>* sub_ortho_svals[4] = { &ortho_svals[0], &ortho_svals[1], &ortho_svals[2], &ortho_svals[3] };
419 , 4, base_element->
sons, sub_trfs, sub_rval
420 , sub_svals, sub_ortho_svals
421 , info_p, perr, rval);
430 template<
typename Scalar>
432 , double3* gip_points,
int num_gip_points
433 ,
const int num_sub,
Element** sub_domains,
Trf** sub_trfs,
int* sons
434 , std::vector<TrfShapeExp>** sub_nonortho_svals, std::vector<TrfShapeExp>** sub_ortho_svals
441 Scalar* right_side =
new Scalar[max_num_shapes];
442 int* shape_inxs =
new int[max_num_shapes];
444 int* indx =
new int[max_num_shapes];
446 double* d =
new double[max_num_shapes];
447 double** proj_matrix = new_matrix<double>(max_num_shapes, max_num_shapes);
449 std::vector<typename OptimumSelector<Scalar>::ShapeInx>& full_shape_indices = this->
shape_indices[mode];
452 bool ortho_svals_available =
true;
453 for (
int i = 0; i < num_sub && ortho_svals_available; i++)
454 ortho_svals_available &= !sub_ortho_svals[i]->empty();
457 std::vector< ValueCacheItem<Scalar> > nonortho_rhs_cache;
458 std::vector< ValueCacheItem<Scalar> > ortho_rhs_cache;
466 double sub_area_corr_coef = 1.0 / num_sub;
471 int order_h =
H2D_GET_H_ORDER(quad_order), order_v = H2D_GET_V_ORDER(quad_order);
475 unsigned int inx_shape = 0;
476 while (inx_shape < full_shape_indices.size())
481 if (num_shapes >= max_num_shapes)
482 throw Exceptions::Exception(
"more shapes than predicted, possible incosistency");
496 std::vector< ValueCacheItem<Scalar> >& rhs_cache = use_ortho ? ortho_rhs_cache : nonortho_rhs_cache;
497 std::vector<TrfShapeExp>** sub_svals = use_ortho ? sub_ortho_svals : sub_nonortho_svals;
502 if (!proj_matrices[order_h][order_v])
506 if (!proj_matrices[order_h][order_v])
508 proj_matrices[order_h][order_v] =
build_projection_matrix(gip_points, num_gip_points, shape_inxs, num_shapes, mode);
514 copy_matrix(proj_matrix, proj_matrices[order_h][order_v], num_shapes, num_shapes);
518 for (
int inx_sub = 0; inx_sub < num_sub; inx_sub++)
520 Element* this_sub_domain = sub_domains[inx_sub];
521 ElemSubTrf this_sub_trf = { sub_trfs[inx_sub], 1 / sub_trfs[inx_sub]->m[0], 1 / sub_trfs[inx_sub]->m[1] };
522 ElemGIP this_sub_gip = { gip_points, num_gip_points };
523 std::vector<TrfShapeExp>& this_sub_svals = *(sub_svals[inx_sub]);
527 int shape_inx = shape_inxs[k];
532 ElemSubShapeFunc this_sub_shape = { shape_inx, this_sub_svals.empty() ? empty_sub_vals : this_sub_svals[shape_inx] };
533 shape_rhs_cache.
set(shape_rhs_cache.
get() +
evaluate_rhs_subdomain(this_sub_domain, this_sub_gip, sons[inx_sub], this_sub_trf, this_sub_shape, rval));
542 right_side[k] = sub_area_corr_coef * rhs_cache_value.
get();
543 rhs_cache_value.
mark();
549 ludcmp(proj_matrix, num_shapes, indx, d);
550 lubksb<double, Scalar>(proj_matrix,
num_shapes, indx, right_side);
554 double error_squared = 0;
555 for (
int inx_sub = 0; inx_sub < num_sub; inx_sub++)
557 Element* this_sub_domain = sub_domains[inx_sub];
558 ElemSubTrf this_sub_trf = { sub_trfs[inx_sub], 1 / sub_trfs[inx_sub]->m[0], 1 / sub_trfs[inx_sub]->m[1] };
559 ElemGIP this_sub_gip = { gip_points, num_gip_points };
560 ElemProj elem_proj = { shape_inxs,
num_shapes, *(sub_svals[inx_sub]), right_side, quad_order };
565 errors_squared[order_h][order_v] = error_squared * sub_area_corr_coef;
566 }
while (order_perm.
next());
568 free_with_check(proj_matrix,
true);
RefinementType split
A refinement, see the enum RefinementType.
unsigned short get_order_v() const
Returns the current vertical order.
int order_v
A minimal vertical order of an element that can use this shape function.
virtual void push_transform(int son)
HERMES_API Trf quad_trf[H2D_TRF_NUM]
A table of quad sub-subdomain transforms. Only first ::H2D_TRF_QUAD_NUM transformations are valid...
virtual void precalc_shapes(const double3 *gip_points, const int num_gip_points, const Trf *trfs, const int num_noni_trfs, const std::vector< typename OptimumSelector< Scalar >::ShapeInx > &shapes, const int max_shape_inx, TrfShape &svals, ElementMode2D mode)
Calculates values of shape function at GIP for all transformations.
std::vector< TrfShapeExp > TrfShape[H2D_TRF_NUM]
Evaluated shapes for all possible transformations for all points. The first index is a transformation...
virtual void precalc_ref_solution(int inx_son, MeshFunction< Scalar > *rsln, Element *element, int intr_gip_order, Scalar *rval[H2D_MAX_ELEMENT_SONS][MAX_NUMBER_FUNCTION_VALUES_FOR_SELECTORS])=0
Returns an array of values of the reference solution at integration points.
A transform shaped function expansions.
Stores one element of a mesh.
#define H2DRS_DEFAULT_ERR_WEIGHT_P
A default multiplicative coefficient of an error of a P-candidate.
virtual void set_active_element(Element *e)
bool uniform_orders
True if all elements of all examined candidates have uniform orders.
void update_cands_info(std::vector< Cand > &candidates, CandsInfo &info_h, CandsInfo &info_p, CandsInfo &info_aniso) const
Updates information about candidates. Initial information is provided.
#define H2DRS_MAX_ORDER
A maximum order suported by refinement selectors.
H-candidates only. Hermes::Orders are not modified.
Information about candidates.
double error_weight_h
A coefficient that multiplies error of H-candidate. The default value is H2DRS_DEFAULT_ERR_WEIGHT_H.
void calc_error_cand_element(const ElementMode2D mode, double3 *gip_points, int num_gip_points, const int num_sub, Element **sub_domains, Trf **sub_trfs, int *sons, std::vector< TrfShapeExp > **sub_nonortho_svals, std::vector< TrfShapeExp > **sub_ortho_svals, const typename OptimumSelector< Scalar >::CandsInfo &info, CandElemProjError errors_squared, Scalar *rval[H2D_MAX_ELEMENT_SONS][MAX_NUMBER_FUNCTION_VALUES_FOR_SELECTORS])
Calculate projection errors of an element of an candidate considering multiple orders.
A shape function on subdomain of an element.
virtual void set_quad_2d(Quad2D *quad_2d)
HERMES_API const char * get_cand_list_str(const CandList cand_list)
Returns a string representation of a predefined candidate list.
bool is_valid() const
Returns true if value is mared as valid.
Represents a function defined on a mesh.
double errors[H2D_MAX_ELEMENT_SONS]
Error of this candidate's sons.
An item of a value cache.
double error
Error of this candidate's sons.
const int max_order
A maximum allowed order.
Integration points in the reference domain of an element of a candidate.
virtual double ** build_projection_matrix(double3 *gip_points, int num_gip_points, const int *shape_inx, const int num_shapes, ElementMode2D)=0
Builds projection matrix using a given set of shapes.
void set_quad_order(unsigned short order, unsigned short mask=H2D_FN_DEFAULT)
double error_weight_aniso
A coefficient that multiplies error of ANISO-candidate. The default value is H2DRS_DEFAULT_ERR_WEIGHT...
CandList cand_list
Allowed candidate types.
bool warn_uniform_orders
True if the selector has already warned about possible inefficiency.
double ** ProjMatrixCache[H2DRS_MAX_ORDER+2][H2DRS_MAX_ORDER+2]
A projection matrix cache type.
virtual void free_ref_solution_data(int inx_son, Scalar *rval[H2D_MAX_ELEMENT_SONS][MAX_NUMBER_FUNCTION_VALUES_FOR_SELECTORS])=0
Frees the data allocated in precalc_ref_solution.
Projection of an element of a candidate.
std::vector< ShapeInx > shape_indices[H2D_NUM_MODES]
Shape indices. The first index is a mode (ElementMode2D).
virtual ~ProjBasedSelector()
Destructor.
unsigned short get_quad_order() const
Returns the current order in an encoded form.
ProjMatrixCache proj_matrix_cache[H2D_NUM_MODES]
An array of projection matrices.
int max_shape_inx[H2D_NUM_MODES]
A maximum index of a shape function. The first index is a mode (ElementMode2D).
T get() const
Returns the value. It does check the state of the value.
A general projection-based selector.
#define H2D_NUM_MODES
Internal.
TrfShape * cached_shape_ortho_vals
Precalculated valus of orthogonalized shape functions.
H- and ANISO-candidates only. Hermes::Orders are not modified.
unsigned short get_order_h() const
Returns the current horizontal order.
CandList
Predefined list of candidates.
double CandElemProjError[H2DRS_MAX_ORDER+2][H2DRS_MAX_ORDER+2]
Error of an element of a candidate for various permutations of orders.
int min_quad_order
Minimum quad order of all elements of all examined candidates.
ANISO-refienement. The element is split along the vertical axis. Quadrilaterals only.
bool * cached_shape_vals_valid
True if shape values were already initialized.
int inx
An index of the shape function.
H- and P-candidates only. Hermes::Orders are modified uniformly.
#define H2D_GET_H_ORDER(encoded_order)
Macros for combining quad horizontal and vertical encoded_orders.
bool next()
Moves to the next permutation of orders.
virtual Scalar evaluate_rhs_subdomain(Element *sub_elem, const ElemGIP &sub_gip, int son, const ElemSubTrf &sub_trf, const ElemSubShapeFunc &sub_shape, Scalar *rval[H2D_MAX_ELEMENT_SONS][MAX_NUMBER_FUNCTION_VALUES_FOR_SELECTORS])=0
Evaluates a value of the right-hande side in a subdomain.
HERMES_API Trf tri_trf[H2D_TRF_NUM]
A table of triangle sub-subdomain transforms. Only first ::H2D_TRF_TRI_NUM transformations are valid...
Should be exactly the same as is the count of enum ShapesetType.
#define H2DRS_INTR_GIP_ORDER
An integration order used to integrate while evaluating a candidate.
TrfShape * cached_shape_vals
Precalculate values of shape functions.
#define H2DRS_DEFAULT_ERR_WEIGHT_H
A default multiplicative coefficient of an error of a H-candidate.
Hermes::Order permutator. Generates all permutations of orders from a set defined by a range of order...
double error_weight_p
A coefficient that multiplies error of P-candidate. The default value is H2DRS_DEFAULT_ERR_WEIGHT_P.
void enable_transform(bool enable=true)
virtual double evaluate_error_squared_subdomain(Element *sub_elem, const ElemGIP &sub_gip, int son, const ElemSubTrf &sub_trf, const ElemProj &elem_proj, Scalar *rval[H2D_MAX_ELEMENT_SONS][MAX_NUMBER_FUNCTION_VALUES_FOR_SELECTORS])=0
Evaluates an squared error of a projection of an element of a candidate onto subdomains.
A transformation from a reference domain of a subdomain to a reference domain of an element of a cand...
TrfShapeExp()
A default contructor. Creates an empty instance.
int next_order_shape[H2D_NUM_MODES][H2DRS_MAX_ORDER+1]
An index to the array OptimumSelector::shape_indices of a shape function of the next uniform order...
A selector that chooses an optimal candidates based on a score.
unsigned short p[H2D_MAX_ELEMENT_SONS]
Encoded orders of sons, see ::H2D_MAKE_QUAD_ORDER. In a case of a triangle, the vertical order is equ...
int max_quad_order
Maximum quad order of all elements of all examined candidates. If less than zero, no candidate is gen...
ANISO-refienement. The element is split along the horizontal axis. Quadrilaterals only...
#define H2D_MAX_ELEMENT_SONS
Macros.
int order_h
A minimal horizonal order of an element that can use this shape function.
virtual void evaluate_cands_error(std::vector< Cand > &candidates, Element *e, MeshFunction< Scalar > *rsln)
Calculates error of candidates.
void set_error_weights(double weight_h=H2DRS_DEFAULT_ERR_WEIGHT_H, double weight_p=H2DRS_DEFAULT_ERR_WEIGHT_P, double weight_aniso=H2DRS_DEFAULT_ERR_WEIGHT_ANISO)
Sets error weights.
Element * sons[H2D_MAX_ELEMENT_SONS]
son elements (up to four)
#define H2DRS_DEFAULT_ERR_WEIGHT_ANISO
A default multiplicative coefficient of an error of a ANISO-candidate.
virtual void precalc_ortho_shapes(const double3 *gip_points, const int num_gip_points, const Trf *trfs, const int num_noni_trfs, const std::vector< typename OptimumSelector< Scalar >::ShapeInx > &shapes, const int max_shape_inx, TrfShape &ortho_svals, ElementMode2D mode)
Calculates values of orthogonalized shape function at GIP for all transformations.
virtual ~TrfShapeExp()
Desructor.
MeshSharedPtr get_mesh() const
Return the mesh.
H-, ANISO- and P-candidates. Hermes::Orders are modified uniformly.
virtual void calc_projection_errors(Element *e, const typename OptimumSelector< Scalar >::CandsInfo &info_h, const typename OptimumSelector< Scalar >::CandsInfo &info_p, const typename OptimumSelector< Scalar >::CandsInfo &info_aniso, MeshFunction< Scalar > *rsln, CandElemProjError herr[H2D_MAX_ELEMENT_SONS], CandElemProjError perr, CandElemProjError anisoerr[H2D_MAX_ELEMENT_SONS])
Calculates projection errors of an elements of candidates for all permutations of orders...
void set(T new_value)
Sets a value.
bool active
0 = active, no sons; 1 = inactive (refined), has sons
void mark(int new_state=H2DRS_VALCACHE_VALID)
Marks a value.
P-candidates only. Hermes::Orders are modified uniformly.
Represents the solution of a PDE.
#define H2DRS_DEFAULT_ORDER
A default order. Used to indicate an unkonwn order or a maximum support order.
bool is_empty() const
Returns true if there are no candidates.