2 #include "element_to_refine.h"
3 #include "optimum_selector.h"
4 #include "order_permutator.h"
6 #define H2DST_ANY H2DST_VERTEX | H2DST_HORIZ_EDGE | H2DST_VERT_EDGE | H2DST_TRI_EDGE | H2DST_BUBBLE
12 namespace RefinementSelectors
14 template<
typename Scalar>
16 max_order,
Shapeset* shapeset,
const Range& vertex_order,
const
17 Range& edge_bubble_order) :
Selector<Scalar>(shapeset->get_min_order(), max_order), cand_list(cand_list), shapeset(shapeset), dof_score_exponent(1.0)
19 if (shapeset ==
nullptr)
20 throw Exceptions::NullException(3);
23 for (
int i = 0; i < 2; i++)
35 memset(
num_shapes[i][j][k], 0, 6 *
sizeof(
int));
45 template<
typename Scalar>
48 for (
int i = 0; i < 2; i++)
54 delete[] num_shapes[i][j][k];
56 delete[] num_shapes[i][j];
58 delete[] num_shapes[i];
63 template<
typename Scalar>
66 int quad_order = H2D_MAKE_QUAD_ORDER(order_h, order_v);
67 const int num_bubbles = shapeset->get_num_bubbles(quad_order, mode);
68 short* bubble_inxs = shapeset->get_bubble_indices(quad_order, mode);
69 for (
int j = 0; j < num_bubbles; j++)
71 int inx_bubble = bubble_inxs[j];
72 if (used_shape_index.find(inx_bubble) == used_shape_index.end())
74 used_shape_index[inx_bubble] =
true;
75 indices.push_back(
ShapeInx(order_h, order_v, inx_bubble, H2DST_BUBBLE));
79 num_shapes[mode][order_h_i][order_v_i][H2DSI_BUBBLE]++;
80 num_shapes[mode][order_h_i][order_v_i][H2DSI_ANY]++;
82 num_shapes[mode][0][0][H2DSI_BUBBLE]++;
83 num_shapes[mode][0][0][H2DSI_ANY]++;
88 template<
typename Scalar>
91 std::vector<ShapeInx> &indices = shape_indices[mode];
92 int* next_order = this->next_order_shape[mode];
93 int& max_shape_inx = this->max_shape_inx[mode];
94 int num_edges = (mode == HERMES_MODE_QUAD) ? 4 : 3;
95 bool &has_vertex = has_vertex_shape[mode];
96 bool &has_edge = has_edge_shape[mode];
97 bool &has_bubble = has_bubble_shape[mode];
102 has_vertex = has_edge = has_bubble =
false;
105 Range order_range = Range::make_envelope(vertex_order, edge_bubble_order);
108 std::map<int, bool> used_shape_index;
112 int examined_shape = 0;
113 for (
unsigned char i = order_range.lower(); i <= 10; i++)
115 if (shapeset->get_space_type() != HERMES_L2_SPACE && shapeset->get_space_type() != HERMES_L2_MARKERWISE_CONST_SPACE)
118 if (vertex_order.is_in_closed(i))
120 for (
int j = 0; j < num_edges; j++)
122 int inx = shapeset->get_vertex_index(j, mode);
125 used_shape_index[inx] =
true;
126 indices.push_back(
ShapeInx(1, 1, inx, H2DST_VERTEX));
127 if (mode == HERMES_MODE_QUAD)
132 num_shapes[mode][order_h_i][order_v_i][H2DSI_VERTEX]++;
133 num_shapes[mode][order_h_i][order_v_i][H2DSI_ANY]++;
135 num_shapes[mode][0][0][H2DSI_VERTEX]++;
136 num_shapes[mode][0][0][H2DSI_ANY]++;
142 num_shapes[mode][order_h_i][0][H2DSI_VERTEX]++;
143 num_shapes[mode][order_h_i][0][H2DSI_ANY]++;
145 num_shapes[mode][0][0][H2DSI_VERTEX]++;
146 num_shapes[mode][0][0][H2DSI_ANY]++;
154 if (edge_bubble_order.is_in_closed(i))
157 if (mode == HERMES_MODE_QUAD)
159 for (
int j = 0; j < num_edges; j++)
161 int inx = shapeset->get_edge_index(j, 0, i, HERMES_MODE_QUAD);
164 used_shape_index[inx] =
true;
167 indices.push_back(
ShapeInx(i, 0, inx, H2DST_HORIZ_EDGE));
171 num_shapes[mode][order_h_i][order_v_i][H2DST_HORIZ_EDGE]++;
172 num_shapes[mode][order_h_i][order_v_i][H2DSI_ANY]++;
174 num_shapes[mode][0][0][H2DST_HORIZ_EDGE]++;
175 num_shapes[mode][0][0][H2DSI_ANY]++;
179 indices.push_back(
ShapeInx(0, i, inx, H2DST_VERT_EDGE));
183 num_shapes[mode][order_h_i][order_v_i][H2DSI_VERT_EDGE]++;
184 num_shapes[mode][order_h_i][order_v_i][H2DSI_ANY]++;
186 num_shapes[mode][0][0][H2DSI_VERT_EDGE]++;
187 num_shapes[mode][0][0][H2DSI_ANY]++;
195 for (
int j = 0; j < num_edges; j++)
197 int inx = shapeset->get_edge_index(j, 0, i, HERMES_MODE_TRIANGLE);
200 used_shape_index[inx] =
true;
201 indices.push_back(
ShapeInx(i, i, inx, H2DST_TRI_EDGE));
204 num_shapes[mode][order_h_i][0][H2DSI_TRI_EDGE]++;
205 num_shapes[mode][order_h_i][0][H2DSI_ANY]++;
207 num_shapes[mode][0][0][H2DSI_TRI_EDGE]++;
208 num_shapes[mode][0][0][H2DSI_ANY]++;
216 if (mode == HERMES_MODE_QUAD)
222 unsigned num_indices_prev = indices.size();
223 for (
int order_other = edge_bubble_order.lower(); order_other <= order; order_other++)
225 add_bubble_shape_index(order, order_other, used_shape_index, indices, mode);
226 add_bubble_shape_index(order_other, order, used_shape_index, indices, mode);
230 if (num_indices_prev < indices.size())
235 unsigned short num_bubbles = shapeset->get_num_bubbles(order, mode);
236 short* bubble_inxs = shapeset->get_bubble_indices(order, mode);
237 for (
unsigned short j = 0; j < num_bubbles; j++)
239 int inx_bubble = bubble_inxs[j];
240 if (used_shape_index.find(inx_bubble) == used_shape_index.end())
242 used_shape_index[inx_bubble] =
true;
243 indices.push_back(
ShapeInx(order, order, inx_bubble, H2DST_BUBBLE));
246 num_shapes[mode][order_h_i][0][H2DSI_BUBBLE]++;
247 num_shapes[mode][order_h_i][0][H2DSI_ANY]++;
249 num_shapes[mode][0][0][H2DSI_BUBBLE]++;
250 num_shapes[mode][0][0][H2DSI_ANY]++;
257 next_order[i] = (int)indices.size();
260 while (examined_shape < next_order[i])
262 max_shape_inx = std::max(max_shape_inx, indices[examined_shape].inx);
267 next_order[i] = (int)indices.size();
271 template<
typename Scalar>
275 bool full_eval =
false;
276 if ((allowed_type_mask & H2DST_VERTEX) != 0)
277 full_eval |= has_vertex_shape[mode];
278 if ((allowed_type_mask & (H2DST_HORIZ_EDGE | H2DST_VERT_EDGE | H2DST_TRI_EDGE)) != 0)
279 full_eval |= has_edge_shape[mode];
280 if ((allowed_type_mask & H2DST_BUBBLE) != 0)
281 full_eval |= has_bubble_shape[mode];
286 std::vector<ShapeInx>& shapes = shape_indices[mode];
288 typename std::vector<ShapeInx>::const_iterator shape = shapes.begin();
289 while (shape != shapes.end())
291 if (((
int)shape->type & allowed_type_mask) != 0)
304 template<
typename Scalar>
308 if (last_order < 0 || start_order < 0)
319 for (
int i = 0; i < num_sons; i++)
321 quad_orders[i] = start_order;
322 quad_perms[i] =
OrderPermutator(start_order, last_order, iso_p, &quad_orders[i]);
332 candidates.push_back(
Cand(split, quad_orders));
333 }
while (quad_perms[0].next());
336 quad_perms[0].
reset();
340 while (inx_son < num_sons && !quad_perms[inx_son].next())
343 quad_perms[inx_son].
reset();
346 if (inx_son >= num_sons)
351 template<
typename Scalar>
354 std::vector<Cand> candidates;
357 int current_min_order, current_max_order;
358 this->get_current_order_range(e, current_min_order, current_max_order);
360 int order_h =
H2D_GET_H_ORDER(quad_order), order_v = H2D_GET_V_ORDER(quad_order);
362 if (current_max_order < std::max(order_h, order_v))
363 current_max_order = std::max(order_h, order_v);
365 bool tri = e->is_triangle();
374 int last_order = H2D_MAKE_QUAD_ORDER(last_order_h, last_order_v);
383 append_candidates_split(candidates, quad_order, last_order,
H2D_REFINEMENT_P, tri || iso_p);
387 int start_order_h = std::max(current_min_order, order_h - 1), start_order_v = std::max(current_min_order, order_v - 1);
388 int start_order = H2D_MAKE_QUAD_ORDER(start_order_h, start_order_v);
390 last_order = H2D_MAKE_QUAD_ORDER(last_order_h, last_order_v);
395 last_order = start_order = quad_order;
break;
401 append_candidates_split(candidates, start_order, last_order,
H2D_REFINEMENT_H, tri || iso_p);
408 int start_order_hz = H2D_MAKE_QUAD_ORDER(order_h, std::max(current_min_order, (order_v - 1)));
410 int start_order_vt = H2D_MAKE_QUAD_ORDER(std::max(current_min_order, (order_h - 1)), order_v);
415 last_order_hz = start_order_hz = quad_order;
416 last_order_vt = start_order_vt = quad_order;
422 int order = std::min(
H2D_GET_H_ORDER(start_order_hz), H2D_GET_V_ORDER(start_order_hz));
423 start_order_hz = H2D_MAKE_QUAD_ORDER(order, order);
424 order = std::min(
H2D_GET_H_ORDER(start_order_vt), H2D_GET_V_ORDER(start_order_vt));
425 start_order_vt = H2D_MAKE_QUAD_ORDER(order, order);
427 order = std::min(
H2D_GET_H_ORDER(last_order_hz), H2D_GET_V_ORDER(last_order_hz));
428 last_order_hz = H2D_MAKE_QUAD_ORDER(order, order);
429 order = std::min(
H2D_GET_H_ORDER(last_order_vt), H2D_GET_V_ORDER(last_order_vt));
430 last_order_vt = H2D_MAKE_QUAD_ORDER(order, order);
439 template<
typename Scalar>
442 for (
unsigned short i = 0; i < candidates.size(); i++)
445 Cand& cand = candidates[i];
449 else {
throw Hermes::Exceptions::Exception(
"Invalid candidate type: %d.", cand.
split); };
453 for (
int i = 0; i < num_elems; i++)
455 int elem_order_h =
H2D_GET_H_ORDER(cand.
p[i]), elem_order_v = H2D_GET_V_ORDER(cand.
p[i]);
456 if (elem_order_h != elem_order_v)
469 template<
typename Scalar>
472 bool tri = e->is_triangle();
474 for (
unsigned i = 0; i < candidates.size(); i++)
476 Cand& c = candidates[i];
483 const int central = 3;
494 if (has_vertex_shape[HERMES_MODE_TRIANGLE])
505 throw Hermes::Exceptions::Exception(
"Unknown split type \"%d\" at candidate %d (element #%d)", c.
split, i, e->
id);
514 c.
dofs += num_shapes[HERMES_MODE_QUAD][
H2D_GET_H_ORDER(c.
p[j]) + 1][H2D_GET_V_ORDER(c.
p[j]) + 1][H2DSI_ANY];
515 for (
int j = 0; j < 2; j++) {
517 c.
dofs -= num_shapes[HERMES_MODE_QUAD][
H2DRS_ORDER_ANY + 1][std::min(H2D_GET_V_ORDER(c.
p[2 * j]), H2D_GET_V_ORDER(c.
p[2 * j + 1])) + 1][H2DSI_VERT_EDGE] / 2;
521 if (has_vertex_shape[HERMES_MODE_QUAD])
527 c.
dofs = num_shapes[HERMES_MODE_QUAD][
H2D_GET_H_ORDER(c.
p[0]) + 1][H2D_GET_V_ORDER(c.
p[0]) + 1][H2DSI_ANY];
528 c.
dofs += num_shapes[HERMES_MODE_QUAD][
H2D_GET_H_ORDER(c.
p[1]) + 1][H2D_GET_V_ORDER(c.
p[1]) + 1][H2DSI_ANY];
531 if (has_vertex_shape[HERMES_MODE_QUAD])
537 c.
dofs = num_shapes[HERMES_MODE_QUAD][
H2D_GET_H_ORDER(c.
p[0]) + 1][H2D_GET_V_ORDER(c.
p[0]) + 1][H2DSI_ANY];
538 c.
dofs += num_shapes[HERMES_MODE_QUAD][
H2D_GET_H_ORDER(c.
p[1]) + 1][H2D_GET_V_ORDER(c.
p[1]) + 1][H2DSI_ANY];
540 c.
dofs -= num_shapes[HERMES_MODE_QUAD][
H2DRS_ORDER_ANY + 1][std::min(H2D_GET_V_ORDER(c.
p[0]), H2D_GET_V_ORDER(c.
p[1])) + 1][H2DSI_VERT_EDGE] / 2;
541 if (has_vertex_shape[HERMES_MODE_QUAD])
547 c.
dofs = num_shapes[HERMES_MODE_QUAD][
H2D_GET_H_ORDER(c.
p[0]) + 1][H2D_GET_V_ORDER(c.
p[0]) + 1][H2DSI_ANY];
551 throw Hermes::Exceptions::Exception(
"Unknown split type \"%d\" at candidate %d", c.
split, i);
557 template<
typename Scalar>
560 evaluate_cands_error(candidates, e, rsln);
562 evaluate_cands_dof(candidates, e, rsln);
564 evaluate_cands_score(candidates, e);
567 template<
typename Scalar>
570 this->dof_score_exponent = exponent;
573 template<
typename Scalar>
577 Cand& unrefined = candidates[0];
581 for (
unsigned short i = 1; i < candidates.size(); i++)
583 Cand& candidate = candidates[i];
587 candidate.
score = (log(unrefined.
error / candidate.
error)) / std::pow(candidate.
dofs - unrefined.
dofs, this->dof_score_exponent);
593 template<
typename Scalar>
599 template<
typename Scalar>
603 const int num_cands = (int)candidates.size();
606 std::sort(candidates.begin() + 1, candidates.end(), compare_cand_score);
609 if (candidates[1].score == 0)
611 best_candidate = &candidates[0];
614 best_candidate = &candidates[1];
616 for (
int i = 0; i < num_cands; i++)
625 for (
int i = 0; i < num_cands; i++)
634 for (
int i = 0; i < num_cands; i++)
643 for (
int i = 0; i < num_cands; i++)
653 template<
typename Scalar>
657 int order_h =
H2D_GET_H_ORDER(quad_order), order_v = H2D_GET_V_ORDER(quad_order);
658 if (element->is_triangle())
662 quad_order = H2D_MAKE_QUAD_ORDER(order_h, order_v);
666 std::vector<Cand> candidates = create_candidates(element, quad_order);
668 Cand* best_candidate;
669 Cand* best_candidates_specific_type[4];
670 memset(best_candidates_specific_type, 0, 4 *
sizeof(
Cand*));
672 if (candidates.size() > 1)
675 evaluate_candidates(candidates, element, rsln);
678 select_best_candidate(candidates, element, best_candidate, best_candidates_specific_type);
684 best_candidate = &candidates[0];
687 if (best_candidate == &candidates[0])
693 for (
int i = 1; i < 4; i++)
694 if (best_candidates_specific_type[i] !=
nullptr)
697 ElementToRefine::copy_errors(refinement.
errors, best_candidate->
errors);
700 if (element->is_triangle())
708 for (
int poly_order_type_i = 1; poly_order_type_i < 4; poly_order_type_i++)
void set_dof_score_exponent(double exponent)
Set the score DOF exponent.
RefinementType split
A refinement, see the enum RefinementType.
P-candidates only. Hermes::Orders are modified non-uniformly.
virtual void select_best_candidate(std::vector< Cand > &candidates, Element *e, Cand *&best_candidate, Cand *best_candidates_specific_type[4])
Sorts and selects the best candidate and the best H-candidate according to the score.
Stores one element of a mesh.
virtual void evaluate_cands_dof(std::vector< Cand > &candidates, Element *e, MeshFunction< Scalar > *rsln)
Calculates DOF of candidates.
virtual std::vector< Cand > create_candidates(Element *e, int quad_order)
Fill a list of candidates.
void build_shape_indices(const ElementMode2D mode, const Range &vertex_order, const Range &edge_bubble_order)
Builds shape index table OptimumSelector::shape_indices.
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.
Represents a function defined on a mesh.
double errors[H2D_MAX_ELEMENT_SONS]
Error of this candidate's sons.
double error
Error of this candidate's sons.
RefinementType
Possible refinements of an element.
static bool compare_cand_score(const Cand &a, const Cand &b)
Compares scores. Used to sort scores ascending.
#define H2DRS_MAX_ORDER_INC
Maximum increase of an order in candidates.
H-, ANISO- and P-candidates. Hermes::Orders are modified non-uniformly.
unsigned short refinement_polynomial_order[H2D_MAX_ELEMENT_SONS]
Encoded orders of sons.
H- and ANISO-candidates only. Hermes::Orders are not modified.
CandList
Predefined list of candidates.
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.
static void copy_orders(unsigned short *dest, const unsigned short *src)
Copies array of orders.
#define H2DRS_ASSUMED_MAX_CANDS
An estimated maximum number of candidates. Used for purpose of reserving space.
unsigned short iro_cache
Increase in integration order, see RefMap::calc_inv_ref_order()
H- and P-candidates only. Hermes::Orders are modified uniformly.
RefinementType split
Proposed refinement. Possible values are defined in the enum RefinementType.
#define H2D_GET_H_ORDER(encoded_order)
Macros for combining quad horizontal and vertical encoded_orders.
OptimumSelector(CandList cand_list, int max_order, Shapeset *shapeset, const Range &vertex_order, const Range &edge_bubble_order)
Constructor.
unsigned short dofs
An estimated number of DOFs.
Should be exactly the same as is the count of enum ShapesetType.
virtual ~OptimumSelector()
Destructor.
virtual void evaluate_cands_score(std::vector< Cand > &candidates, Element *e)
Evalutes score of candidates.
Hermes::Order permutator. Generates all permutations of orders from a set defined by a range of order...
virtual bool select_refinement(Element *element, int quad_order, MeshFunction< Scalar > *rsln, ElementToRefine &refinement)
Selects a refinement.
#define H2DRS_ORDER_ANY
Any order. Used as a wildcard to indicate that a given order can by any valid order.
A selector that chooses an optimal candidates based on a score.
HERMES_API int get_refin_sons(const RefinementType refin_type)
Returns a maximum number of sons that will be generated if a given refinement is applied.
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...
double errors[H2D_MAX_ELEMENT_SONS]
Error of the selected candidate.
ANISO-refienement. The element is split along the horizontal axis. Quadrilaterals only...
A parent of all refinement selectors. Abstract class.
#define H2D_MAX_ELEMENT_SONS
Macros.
int calc_num_shapes(int mode, int order_h, int order_v, int allowed_type_mask)
Returns a number of shapes that may be contained in an element of a given order.
void reset()
Resets permutator to the starting order.
void add_bubble_shape_index(int order_h, int order_v, std::map< int, bool > &used_shape_index, std::vector< ShapeInx > &indices, ElementMode2D mode)
Adds an index (or indices) of a bubble function of a given order if the shape index was not used yet...
H-, ANISO- and P-candidates. Hermes::Orders are modified uniformly.
double score
A score of a candidate: the higher the better. If zero, the score is not valid and a candidate should...
unsigned char get_num_elems() const
Returns a number of elements of a candidate.
P-candidates only. Hermes::Orders are modified uniformly.
void append_candidates_split(std::vector< Cand > &candidates, const int start_quad_order, const int last_order, const RefinementType split, bool iso_p)
Appends cancidates of a given refinement and a given range of orders.
unsigned short best_refinement_polynomial_order_type[4][H2D_MAX_ELEMENT_SONS]
void evaluate_candidates(std::vector< Cand > &candidates, Element *e, MeshFunction< Scalar > *rsln)
Calculates error, dofs, and score of candidates.
#define H2D_NUM_SHAPES_SIZE
A maximum order suported by refinement selectors.