bool OrderPermutator::next() { if(iso_p) { if(order_h >= end_order_h || order_v >= end_order_v) return false; order_h++; order_v++; } else { if(order_h >= end_order_h && order_v >= end_order_v) return false; order_h++; if(order_h > end_order_h) { order_h = start_order_h; order_v++; } } if(tgt_quad_order != NULL) *tgt_quad_order = H2D_MAKE_QUAD_ORDER(order_h, order_v); return true; }
void OrderPermutator::reset() { order_h = start_order_h; order_v = start_order_v; if(tgt_quad_order != NULL) *tgt_quad_order = H2D_MAKE_QUAD_ORDER(order_h, order_v); }
void RefMap::set_active_element(Element* e) { if (e != element) free(); ref_map_pss.set_active_element(e); quad_2d->set_mode(e->get_mode()); num_tables = quad_2d->get_num_tables(); assert(num_tables <= H2D_MAX_TABLES); if (e == element) return; element = e; reset_transform(); update_cur_node(); is_const = !element->is_curved() && (element->is_triangle() || is_parallelogram()); // prepare the shapes and coefficients of the reference map int j, k = 0; for (unsigned int i = 0; i < e->nvert; i++) indices[k++] = ref_map_shapeset.get_vertex_index(i); // straight-edged element if (e->cm == NULL) { for (unsigned int i = 0; i < e->nvert; i++) { lin_coeffs[i][0] = e->vn[i]->x; lin_coeffs[i][1] = e->vn[i]->y; } coeffs = lin_coeffs; nc = e->nvert; } else // curvilinear element - edge and bubble shapes { int o = e->cm->order; for (unsigned int i = 0; i < e->nvert; i++) for (j = 2; j <= o; j++) indices[k++] = ref_map_shapeset.get_edge_index(i, 0, j); if (e->is_quad()) o = H2D_MAKE_QUAD_ORDER(o, o); memcpy(indices + k, ref_map_shapeset.get_bubble_indices(o), ref_map_shapeset.get_num_bubbles(o) * sizeof(int)); coeffs = e->cm->coeffs; nc = e->cm->nc; } // calculate the order of the inverse reference map if (element->iro_cache == -1 && quad_2d->get_max_order() > 1) { element->iro_cache = is_const ? 0 : calc_inv_ref_order(); } inv_ref_order = element->iro_cache; // constant inverse reference map if (is_const) calc_const_inv_ref_map(); else const_jacobian = 0.0; }
void Space<Scalar>::set_element_order_internal(int id, int order) { if(id < 0 || id >= mesh->get_max_element_id()) throw Hermes::Exceptions::Exception("Space<Scalar>::set_element_order_internal: Invalid element id."); resize_tables(); if(mesh->get_element(id)->is_quad() && get_type() != HERMES_L2_SPACE && H2D_GET_V_ORDER(order) == 0) order = H2D_MAKE_QUAD_ORDER(order, order); edata[id].order = order; seq = g_space_seq++; }
// just sets the element order without enumerating dof void Space::set_element_order_internal(int id, int order) { //NOTE: We need to take into account that L2 and Hcurl may use zero orders. The latter has its own version of this method, however. assert_msg(mesh->get_element(id)->is_triangle() || get_type() == 3 || H2D_GET_V_ORDER(order) != 0, "Element #%d is quad but given vertical order is zero", id); assert_msg(mesh->get_element(id)->is_quad() || H2D_GET_V_ORDER(order) == 0, "Element #%d is triangle but vertical is not zero", id); if (id < 0 || id >= mesh->get_max_element_id()) error("Invalid element id."); H2D_CHECK_ORDER(order); resize_tables(); if (mesh->get_element(id)->is_quad() && get_type() != 3 && H2D_GET_V_ORDER(order) == 0) order = H2D_MAKE_QUAD_ORDER(order, order); edata[id].order = order; seq++; }
void Space::set_element_orders(int* elem_orders_) { resize_tables(); Element* e; int counter = 0; for_all_elements(e, mesh) { H2D_CHECK_ORDER(elem_orders_[counter]); ElementData* ed = &edata[e->id]; if (e->is_triangle()) ed->order = elem_orders_[counter]; else ed->order = H2D_MAKE_QUAD_ORDER(elem_orders_[counter], elem_orders_[counter]); counter++; }
void Space<Scalar>::set_element_orders(int* elem_orders_) { resize_tables(); Element* e; int counter = 0; for_all_elements(e, mesh) { assert(elem_orders_[counter] >= 0 && elem_orders_[counter] <= shapeset->get_max_order()); ElementData* ed = &edata[e->id]; if(e->is_triangle()) ed->order = elem_orders_[counter]; else ed->order = H2D_MAKE_QUAD_ORDER(elem_orders_[counter], elem_orders_[counter]); counter++; }
Hermes::vector<Cand> create_candidates(Element* e, int quad_order) { Hermes::vector<Cand> candidates; // Get the current order range. int current_min_order, current_max_order; this->get_current_order_range(e, current_min_order, current_max_order); int order_h = H2D_GET_H_ORDER(quad_order), order_v = H2D_GET_V_ORDER(quad_order); if(current_max_order < std::max(order_h, order_v)) current_max_order = std::max(order_h, order_v); int last_order_h = std::min(current_max_order, order_h + 1), last_order_v = std::min(current_max_order, order_v + 1); int last_order = H2D_MAKE_QUAD_ORDER(last_order_h, last_order_v); switch(strategy) { case(hORpSelectionBasedOnDOFs): { candidates.push_back(Cand(H2D_REFINEMENT_P, quad_order)); } case(hXORpSelectionBasedOnError): { candidates.push_back(Cand(H2D_REFINEMENT_P, last_order)); candidates.push_back(Cand(H2D_REFINEMENT_H, quad_order, quad_order, quad_order, quad_order)); return candidates; } break; case(isoHPSelectionBasedOnDOFs): { this->cand_list = H2D_HP_ISO; return H1ProjBasedSelector<complex>::create_candidates(e, quad_order); } break; case(anisoHPSelectionBasedOnDOFs): { this->cand_list = H2D_HP_ANISO; return H1ProjBasedSelector<complex>::create_candidates(e, quad_order); } break; } }
void Space<Scalar>::set_uniform_order_internal(int order, int marker) { resize_tables(); int quad_order = H2D_MAKE_QUAD_ORDER(order, order); Element* e; for_all_active_elements(e, mesh) { if(marker == HERMES_ANY_INT || e->marker == marker) { ElementData* ed = &edata[e->id]; if(e->is_triangle()) ed->order = order; else ed->order = quad_order; } } seq = g_space_seq++; }
void Adapt<Scalar>::homogenize_shared_mesh_orders(Mesh** meshes) { Element* e; for (int i = 0; i < this->num; i++) { for_all_active_elements(e, meshes[i]) { int current_quad_order = this->spaces[i]->get_element_order(e->id); int current_order_h = H2D_GET_H_ORDER(current_quad_order), current_order_v = H2D_GET_V_ORDER(current_quad_order); for (int j = 0; j < this->num; j++) if ((j != i) && (meshes[j] == meshes[i])) // components share the mesh { int quad_order = this->spaces[j]->get_element_order(e->id); current_order_h = std::max(current_order_h, H2D_GET_H_ORDER(quad_order)); current_order_v = std::max(current_order_v, H2D_GET_V_ORDER(quad_order)); } this->spaces[i]->set_element_order_internal(e->id, H2D_MAKE_QUAD_ORDER(current_order_h, current_order_v)); } }
bool POnlySelector<Scalar>::select_refinement(Element* element, int quad_order, Solution<Scalar>* rsln, ElementToRefine& refinement) { refinement.split = H2D_REFINEMENT_P; //determin max. order int max_allowed_order = this->max_order; if (this->max_order == H2DRS_DEFAULT_ORDER) max_allowed_order = H2DRS_MAX_ORDER; //calculate new order int order_h = H2D_GET_H_ORDER(quad_order), order_v = H2D_GET_V_ORDER(quad_order); int new_order_h = std::min(max_allowed_order, order_h + order_h_inc); int new_order_v = std::min(max_allowed_order, order_v + order_v_inc); if (element->is_triangle()) refinement.p[0] = refinement.q[0] = new_order_h; else refinement.p[0] = refinement.q[0] = H2D_MAKE_QUAD_ORDER(new_order_h, new_order_v); //decide if successful if (new_order_h > order_h || new_order_v > order_v) return true; else return false; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; H2DReader mloader; // We load the mesh on a (-1, 1)^2 domain. mloader.load("ref_square.mesh", &mesh); // Enter boundary markers // (If no markers are entered, default is a natural BC). BCTypes bc_types; // Create an H1 space with default shapeset, // natural BC, and linear elements. H1Space space(&mesh, &bc_types, P_INIT); // The type of element, mesh_mode = 4 means a rectangle element. int mesh_mode = 4; int ndof = Space::get_num_dofs(&space); printf("ndof = %d\n", ndof); if(ndof > FNS_NUM) error("Max number of shape functions exceeded."); int *fn_idx = new int [FNS_NUM]; int m = 0; int order = P_INIT; // Get the vertex fns index. info("Get the vertex fns index."); for (int i = 0; i < mesh_mode; i++, m++) { fn_idx[m] = space.get_shapeset()->get_vertex_index(i); printf("m = %d, get_vertex_index(m) = %d\n", m, space.get_shapeset()->get_vertex_index(m)); } // Get the edge fns index. info("Get the edge fns index."); for (int edge_order = 2; edge_order <= order; edge_order++) { for (int j = 0; j < mesh_mode; j++, m++) { fn_idx[m] = space.get_shapeset()->get_edge_index(j, 0, edge_order); printf("m = %d, get_edge_index(m) = %d\n", m, fn_idx[m]); } } // Get the bubble fns index. info("Get the bubble fns index."); int number_bubble = space.get_shapeset()->get_num_bubbles(H2D_MAKE_QUAD_ORDER(order, order)); int *bubble_idx = space.get_shapeset()->get_bubble_indices(H2D_MAKE_QUAD_ORDER(order, order)); for (int i = 0; i < number_bubble; i++, m++ ) { fn_idx[m] = bubble_idx[i]; printf("m = %d, get_bubble_index(m) = %d\n", m, fn_idx[m]); } // Initialize the matrix solver. SparseMatrix* mat = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, mat, rhs); // precalc structure mat->prealloc(ndof); for (int i = 0; i < ndof; i++) for (int j = 0; j < ndof; j++) mat->pre_add_ij(i, j); mat->alloc(); rhs->alloc(ndof); info("Assembling matrix ..."); for (int i = 0; i < ndof; i++) { for (int j = 0; j < order; j++) { double x1 = -1 + (2.0/order)*j; double y1 = -1; double value = space.get_shapeset()->get_fn_value(fn_idx[i], x1, y1, 0); mat->add(i, j, value); printf("get fn[%d] value = %f ", i, value); printf("x1 = %f, y1 = %f\n", x1, y1); } for (int j = 0; j < order; j++) { double y2 = -1 + (2.0/order)*j;; double x2 = 1; double value = space.get_shapeset()->get_fn_value(fn_idx[i], x2, y2, 0); mat->add(i, j+order, value); printf("get fn[%d] value = %f ", i, value); printf("x2 = %f, y2 = %f\n", x2, y2); } for (int j = 0; j < order; j++) { double x3 = 1 + (-1.0)*(2.0/order)*j; double y3 = 1; double value = space.get_shapeset()->get_fn_value(fn_idx[i], x3, y3, 0); mat->add(i, j+2*order, value); printf("get fn[%d] value = %f ", i, value); printf("x3 = %f, y3 = %f\n", x3, y3); } for (int j = 0; j < order; j++) { double x4 = -1; double y4 = 1 + (-1.0)*(2.0/order)*j; double value = space.get_shapeset()->get_fn_value(fn_idx[i], x4, y4, 0); mat->add(i, j+3*order, value); printf("get fn[%d] value = %f ", i, value); printf("x4 = %f, y4 = %f\n", x4, y4); } } int bubble = 0; for (int i = order*4; i < ndof; i++) { double x = 0.0 + (1.0/number_bubble)*bubble; double y = 0.0 + (1.0/number_bubble)*bubble; double value = space.get_shapeset()->get_fn_value(fn_idx[i], x, y, 0); mat->add(i, i, value); printf("get fn[%d] value = %f ", i, value); printf("x = %f, y = %f\n", x, y); bubble++; } printf("Adding the rhs\n"); for (int i = 0; i < ndof; i++) { rhs->add(i, 0.0); } // Initialize the solution. Solution sln; info("Solution ..."); if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), &space, &sln); else error ("Matrix solver failed.\n"); for (int i = 0; i < ndof; i++) { // Get the value of the matrix solution by calling Vector::get(). if (rhs->get(i) >= EPS) { printf("Shape functions are not linearly independent\n"); return ERR_FAILURE; } } printf("Success!\n"); // Clean up. delete solver; delete mat; delete rhs; delete [] fn_idx; return ERR_SUCCESS; }
int main(int argc, char* argv[]) { // Read the command-line arguments. if (argc != 10) error("You must provide 5 real numbers (mesh vertices) and 4 integers (poly degrees)."); double x0 = atof(argv[1]); double x1 = atof(argv[2]); double x2 = atof(argv[3]); double x3 = atof(argv[4]); double x4 = atof(argv[5]); int o0 = atoi(argv[6]); int o1 = atoi(argv[7]); int o2 = atoi(argv[8]); int o3 = atoi(argv[9]); // Prepare mesh geometry. int nv = 10; double2 verts[10]; verts[0][0] = x0; verts[0][1] = 0; verts[1][0] = x1; verts[1][1] = 0; verts[2][0] = x2; verts[2][1] = 0; verts[3][0] = x3; verts[3][1] = 0; verts[4][0] = x4; verts[4][1] = 0; verts[5][0] = x0; verts[5][1] = 1; verts[6][0] = x1; verts[6][1] = 1; verts[7][0] = x2; verts[7][1] = 1; verts[8][0] = x3; verts[8][1] = 1; verts[9][0] = x4; verts[9][1] = 1; int nt = 0; int4* tris = NULL; int nq = 4; int5 quads[4]; quads[0][0] = 0; quads[0][1] = 1; quads[0][2] = 6; quads[0][3] = 5; quads[0][4] = 0; quads[1][0] = 1; quads[1][1] = 2; quads[1][2] = 7; quads[1][3] = 6; quads[1][4] = 0; quads[2][0] = 2; quads[2][1] = 3; quads[2][2] = 8; quads[2][3] = 7; quads[2][4] = 0; quads[3][0] = 3; quads[3][1] = 4; quads[3][2] = 9; quads[3][3] = 8; quads[3][4] = 0; int nm = 10; int3 mark[10]; mark[0][0] = 0; mark[0][1] = 1; mark[0][2] = 1; mark[1][0] = 1; mark[1][1] = 2; mark[1][2] = 1; mark[2][0] = 2; mark[2][1] = 3; mark[2][2] = 1; mark[3][0] = 3; mark[3][1] = 4; mark[3][2] = 1; mark[4][0] = 4; mark[4][1] = 9; mark[4][2] = 1; mark[5][0] = 9; mark[5][1] = 8; mark[5][2] = 1; mark[6][0] = 8; mark[6][1] = 7; mark[6][2] = 1; mark[7][0] = 7; mark[7][1] = 6; mark[7][2] = 1; mark[8][0] = 6; mark[8][1] = 5; mark[8][2] = 1; mark[9][0] = 5; mark[9][1] = 0; mark[9][2] = 1; // Create a mesh with 10 vertices, 4 elements and 10 boundary // edges from the above data. Mesh mesh; mesh.create(nv, verts, nt, tris, nq, quads, nm, mark); // Create an H1 space with default shapeset. H1Space space(&mesh, NULL, NULL, P_INIT); // Set element poly orders. space.set_element_order(0, H2D_MAKE_QUAD_ORDER(o0, 1)); space.set_element_order(1, H2D_MAKE_QUAD_ORDER(o1, 1)); space.set_element_order(2, H2D_MAKE_QUAD_ORDER(o2, 1)); space.set_element_order(3, H2D_MAKE_QUAD_ORDER(o3, 1)); // Perform orthogonal projection in the H1 norm. Solution sln_approx; ExactSolution sln_exact(&mesh, init_cond); project_global(&space, H2D_H1_NORM, &sln_exact, &sln_approx); // Calculate the error. double err = calc_abs_error(&sln_approx, &sln_exact, H2D_H1_NORM); printf("\nMesh: %g, %g, %g, %g, %g\n", x0, x1, x2, x3, x4); printf("Poly degrees: %d, %d, %d, %d\n", o0, o1, o2, o3); printf("err = %g, err_squared = %g\n\n", err, err*err); /* // Visualise the solution and mesh. WinGeom* sln_win_geom = new WinGeom(0, 0, 440, 350); ScalarView sview("Solution", sln_win_geom); sview.show(&sln_approx); WinGeom* mesh_win_geom = new WinGeom(450, 0, 400, 350); OrderView oview("Mesh", mesh_win_geom); oview.show(&space); // Wait for all views to be closed. View::wait(); return 0; */ }
int OrderPermutator::get_end_quad_order() const { return H2D_MAKE_QUAD_ORDER(end_order_h, end_order_v); }
int OrderPermutator::get_start_quad_order() const { return H2D_MAKE_QUAD_ORDER(start_order_h, start_order_v); }
void L2OrthoHP::calc_ortho_base() { int i, j, k, l, m, ii, nb, np, o, r; int n, idx[121]; H1Shapeset shapeset; // allocate the orthonormal base tables - these are simply the values of the // orthonormal functions in integration points; we store the basic functions // plus four son cut-outs of them (i.e. 5 times) for (i = 0; i < 9; i++) { if ((i < 4) || (i >= 8)) obase[0][i] = new_matrix<double3>(66, 79); // tri obase[1][i] = new_matrix<double3>(121, 121); // quad } // repeat for triangles and quads for (m = 0; m <= 1; m++) { shapeset.set_mode(m); // obtain a list of all shape functions up to the order 10, from lowest to highest order n = 0; int nv = m ? 4 : 3; int num_sons = m ? 8 : 4; for (i = 0; i < nv; i++) idx[n++] = shapeset.get_vertex_index(i); basecnt[m][0] = 0; basecnt[m][1] = n; for (i = 2; i <= 10; i++) { for (j = 0; j < nv; j++) idx[n++] = shapeset.get_edge_index(j, 0, i); ii = m ? H2D_MAKE_QUAD_ORDER(i, i) : i; nb = shapeset.get_num_bubbles(ii); int* bub = shapeset.get_bubble_indices(ii); for (j = 0; j < nb; j++) { o = shapeset.get_order(bub[j]); if (H2D_GET_H_ORDER(o) == i || H2D_GET_V_ORDER(o) == i) idx[n++] = bub[j]; } basecnt[m][i] = n; } // obtain their values for integration rule 20 g_quad_2d_std.set_mode(m); np = g_quad_2d_std.get_num_points(20); double3* pt = g_quad_2d_std.get_points(20); for (i = 0; i < n; i++) for (j = 0; j < np; j++) for (k = 0; k < 3; k++) obase[m][8][i][j][k] = shapeset.get_value(k, idx[i], pt[j][0], pt[j][1], 0); for (l = 0; l < num_sons; l++) { Trf* tr = (m ? quad_trf : tri_trf) + l; for (i = 0; i < n; i++) for (j = 0; j < np; j++) { double x = tr->m[0]*pt[j][0] + tr->t[0], y = tr->m[1]*pt[j][1] + tr->t[1]; for (k = 0; k < 3; k++) obase[m][l][i][j][k] = shapeset.get_value(k, idx[i], x, y, 0); } } // orthonormalize the basis functions for (i = 0; i < n; i++) { for (j = 0; j < i; j++) { double prod = 0.0; for (k = 0; k < np; k++) { double sum = 0.0; for (r = 0; r < 1; r++) sum += obase[m][8][i][k][r] * obase[m][8][j][k][r]; prod += pt[k][2] * sum; } for (l = 0; l < 9; l++) if (m || l < 4 || l >= 8) for (k = 0; k < np; k++) for (r = 0; r < 1; r++) obase[m][l][i][k][r] -= prod * obase[m][l][j][k][r]; } double norm = 0.0; for (k = 0; k < np; k++) { double sum = 0.0; for (r = 0; r < 1; r++) sum += sqr(obase[m][8][i][k][r]); norm += pt[k][2] * sum; } norm = sqrt(norm); for (l = 0; l < 9; l++) if (m || l < 4 || l >= 8) for (k = 0; k < np; k++) for (r = 0; r < 1; r++) obase[m][l][i][k][r] /= norm; } // check the orthonormal base /* if (m) { for (i = 0; i < n; i++) for (j = 0; j < n; j++) { double check = 0.0; for(int son = 4; son < 6; son++ ) for (k = 0; k < np; k++) check += pt[k][2] * (obase[m][son][i][k][0] * obase[m][son][j][k][0] + obase[m][son][i][k][1] * obase[m][son][j][k][1] + obase[m][son][i][k][2] * obase[m][son][j][k][2]); check *= 0.5; if ((i == j && fabs(check - 1.0) > 1e-8) || (i != j && fabs(check) > 1e-8)) warn("Not orthonormal: base %d times base %d = %g", i, j , check); } }*/ } obase_ready = true; }
int main(int argc, char* argv[]) { // Initialize the library's global functions. Hermes2D hermes2D; // Read the command-line arguments. if (argc != 10) error("You must provide 5 real numbers (mesh vertices) and 4 integers (poly degrees)."); double x0 = atof(argv[1]); double x1 = atof(argv[2]); double x2 = atof(argv[3]); double x3 = atof(argv[4]); double x4 = atof(argv[5]); int o0 = atoi(argv[6]); int o1 = atoi(argv[7]); int o2 = atoi(argv[8]); int o3 = atoi(argv[9]); // Prepare mesh geometry. int nv = 10; double2 verts[10]; verts[0][0] = x0; verts[0][1] = 0; verts[1][0] = x1; verts[1][1] = 0; verts[2][0] = x2; verts[2][1] = 0; verts[3][0] = x3; verts[3][1] = 0; verts[4][0] = x4; verts[4][1] = 0; verts[5][0] = x0; verts[5][1] = 1; verts[6][0] = x1; verts[6][1] = 1; verts[7][0] = x2; verts[7][1] = 1; verts[8][0] = x3; verts[8][1] = 1; verts[9][0] = x4; verts[9][1] = 1; int nt = 0; int4* tris = NULL; int nq = 4; int5 quads[4]; quads[0][0] = 0; quads[0][1] = 1; quads[0][2] = 6; quads[0][3] = 5; quads[0][4] = 0; quads[1][0] = 1; quads[1][1] = 2; quads[1][2] = 7; quads[1][3] = 6; quads[1][4] = 0; quads[2][0] = 2; quads[2][1] = 3; quads[2][2] = 8; quads[2][3] = 7; quads[2][4] = 0; quads[3][0] = 3; quads[3][1] = 4; quads[3][2] = 9; quads[3][3] = 8; quads[3][4] = 0; int nm = 10; int3 mark[10]; mark[0][0] = 0; mark[0][1] = 1; mark[0][2] = 1; mark[1][0] = 1; mark[1][1] = 2; mark[1][2] = 1; mark[2][0] = 2; mark[2][1] = 3; mark[2][2] = 1; mark[3][0] = 3; mark[3][1] = 4; mark[3][2] = 1; mark[4][0] = 4; mark[4][1] = 9; mark[4][2] = 1; mark[5][0] = 9; mark[5][1] = 8; mark[5][2] = 1; mark[6][0] = 8; mark[6][1] = 7; mark[6][2] = 1; mark[7][0] = 7; mark[7][1] = 6; mark[7][2] = 1; mark[8][0] = 6; mark[8][1] = 5; mark[8][2] = 1; mark[9][0] = 5; mark[9][1] = 0; mark[9][2] = 1; // Create a mesh with 10 vertices, 4 elements and 10 boundary // edges from the above data. Mesh mesh; mesh.create(nv, verts, nt, tris, nq, quads, nm, mark); // Create an H1 space with default shapeset. H1Space space(&mesh, P_INIT); // Set element poly orders. space.set_element_order(0, H2D_MAKE_QUAD_ORDER(o0, 1)); space.set_element_order(1, H2D_MAKE_QUAD_ORDER(o1, 1)); space.set_element_order(2, H2D_MAKE_QUAD_ORDER(o2, 1)); space.set_element_order(3, H2D_MAKE_QUAD_ORDER(o3, 1)); // Perform orthogonal projection in the H1 norm. Solution sln_approx; CustomExactSolution sln_exact(&mesh, K); OGProjection::project_global(&space, &sln_exact, &sln_approx); // Calculate the error. double err = hermes2D.calc_abs_error(&sln_approx, &sln_exact, HERMES_H1_NORM); printf("\nMesh: %g, %g, %g, %g, %g\n", x0, x1, x2, x3, x4); printf("Poly degrees: %d, %d, %d, %d\n", o0, o1, o2, o3); printf("err = %g, err_squared = %g\n\n", err, err*err); // Mesh: 0, 1, 2, 3, 4 // Poly degrees: 10, 10, 10, 10 if ((err - 0.04381394) < 1E-6) { printf("Success!\n"); return ERR_SUCCESS; } else { printf("Failure!\n"); return ERR_FAILURE; } }
int main(int argc, char* argv[]) { // Read the command-line arguments. if (argc != 10) error("You must provide 5 real numbers (mesh vertices) and 4 integers (poly degrees)."); double x0 = atof(argv[1]); double x1 = atof(argv[2]); double x2 = atof(argv[3]); double x3 = atof(argv[4]); double x4 = atof(argv[5]); int o0 = atoi(argv[6]); int o1 = atoi(argv[7]); int o2 = atoi(argv[8]); int o3 = atoi(argv[9]); // Prepare mesh geometry. int nv = 10; double2 verts[10]; verts[0][0] = x0; verts[0][1] = 0; verts[1][0] = x1; verts[1][1] = 0; verts[2][0] = x2; verts[2][1] = 0; verts[3][0] = x3; verts[3][1] = 0; verts[4][0] = x4; verts[4][1] = 0; verts[5][0] = x0; verts[5][1] = 1; verts[6][0] = x1; verts[6][1] = 1; verts[7][0] = x2; verts[7][1] = 1; verts[8][0] = x3; verts[8][1] = 1; verts[9][0] = x4; verts[9][1] = 1; int nt = 0; int4* tris = NULL; int nq = 4; int5 quads[4]; quads[0][0] = 0; quads[0][1] = 1; quads[0][2] = 6; quads[0][3] = 5; quads[0][4] = 0; quads[1][0] = 1; quads[1][1] = 2; quads[1][2] = 7; quads[1][3] = 6; quads[1][4] = 0; quads[2][0] = 2; quads[2][1] = 3; quads[2][2] = 8; quads[2][3] = 7; quads[2][4] = 0; quads[3][0] = 3; quads[3][1] = 4; quads[3][2] = 9; quads[3][3] = 8; quads[3][4] = 0; int nm = 10; int3 mark[10]; mark[0][0] = 0; mark[0][1] = 1; mark[0][2] = 1; mark[1][0] = 1; mark[1][1] = 2; mark[1][2] = 1; mark[2][0] = 2; mark[2][1] = 3; mark[2][2] = 1; mark[3][0] = 3; mark[3][1] = 4; mark[3][2] = 1; mark[4][0] = 4; mark[4][1] = 9; mark[4][2] = 1; mark[5][0] = 9; mark[5][1] = 8; mark[5][2] = 1; mark[6][0] = 8; mark[6][1] = 7; mark[6][2] = 1; mark[7][0] = 7; mark[7][1] = 6; mark[7][2] = 1; mark[8][0] = 6; mark[8][1] = 5; mark[8][2] = 1; mark[9][0] = 5; mark[9][1] = 0; mark[9][2] = 1; // Create a mesh with 10 vertices, 4 elements and 10 boundary // edges from the above data. Mesh mesh; mesh.create(nv, verts, nt, tris, nq, quads, nm, mark); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_neumann(Hermes::Tuple<int>(BDY_LEFT_RIGHT, BDY_TOP_BOTTOM)); // Create an H1 space with default shapeset. H1Space space(&mesh, &bc_types, P_INIT); // Set element poly orders. space.set_element_order(0, H2D_MAKE_QUAD_ORDER(o0, 1)); space.set_element_order(1, H2D_MAKE_QUAD_ORDER(o1, 1)); space.set_element_order(2, H2D_MAKE_QUAD_ORDER(o2, 1)); space.set_element_order(3, H2D_MAKE_QUAD_ORDER(o3, 1)); // Perform orthogonal projection in the H1 norm. Solution sln_approx; ExactSolution sln_exact(&mesh, init_cond); OGProjection::project_global(&space, &sln_exact, &sln_approx); // Calculate the error. double err = calc_abs_error(&sln_approx, &sln_exact, HERMES_H1_NORM); printf("\nMesh: %g, %g, %g, %g, %g\n", x0, x1, x2, x3, x4); printf("Poly degrees: %d, %d, %d, %d\n", o0, o1, o2, o3); printf("err = %g, err_squared = %g\n\n", err, err*err); // Mesh: 0, 1, 2, 3, 4 // Poly degrees: 10, 10, 10, 10 // err = 2.11454e-09, err_squared = 4.47128e-18 if ((err - 2.11454e-09) < 1E-6) { // err was 2.11454e-09 at the time this test was created printf("Success!\n"); return ERR_SUCCESS; } else { printf("Failure!\n"); return ERR_FAILURE; } }
void RefSystem::global_refinement() { // after this, meshes and spaces are NULL this->free_spaces(); // create new meshes and spaces this->meshes = new Mesh*[this->wf->neq]; this->spaces = new Space*[this->wf->neq]; this->sp_seq = new int[this->wf->neq]; int i, j; // copy meshes from the coarse problem and refine them for (i = 0; i < this->wf->neq; i++) { Mesh* mesh = base->spaces[i]->get_mesh(); // check if we already have the same mesh for (j = 0; j < i; j++) if (mesh->get_seq() == base->spaces[j]->get_mesh()->get_seq()) break; if (j < i) // yes { meshes[i] = meshes[j]; } else // no, copy and refine the coarse one { Mesh* rmesh = new Mesh; rmesh->copy(mesh); if (refinement == 1) rmesh->refine_all_elements(); if (refinement == -1) rmesh->unrefine_all_elements(); this->meshes[i] = rmesh; } } // duplicate spaces from the coarse problem, assign reference orders and dofs int ndof = 0; for (i = 0; i < this->wf->neq; i++) { this->spaces[i] = this->base->spaces[i]->dup(this->meshes[i]); if (refinement == -1) { Element* re; for_all_active_elements(re, meshes[i]) { Mesh* mesh = this->base->spaces[i]->get_mesh(); Element* e = mesh->get_element(re->id); int max_order_h = 0, max_order_v = 0; if (e->active) { int quad_order = base->spaces[i]->get_element_order(e->id); max_order_h = H2D_GET_H_ORDER(quad_order); max_order_v = H2D_GET_V_ORDER(quad_order); } else { //find maximum order of sons for (int son = 0; son < 4; son++) { if (e->sons[son] != NULL) { int quad_order = base->spaces[i]->get_element_order(e->sons[son]->id); max_order_h = std::max(max_order_h, H2D_GET_H_ORDER(quad_order)); max_order_v = std::max(max_order_v, H2D_GET_V_ORDER(quad_order)); } } } //increase order and set it to element max_order_h = std::max(1, max_order_h + order_increase); if (re->is_triangle()) max_order_v = 0; else max_order_v = std::max(1, max_order_v + order_increase); spaces[i]->set_element_order_internal(re->id, H2D_MAKE_QUAD_ORDER(max_order_h, max_order_v)); } }
bool select_refinement(Element* element, int order, MeshFunction<complex>* rsln, ElementToRefine& refinement) { switch(strategy) { case(noSelectionH): { refinement.split = H2D_REFINEMENT_H; refinement.best_refinement_polynomial_order_type[H2D_REFINEMENT_H][0] = refinement.best_refinement_polynomial_order_type[H2D_REFINEMENT_H][1] = refinement.best_refinement_polynomial_order_type[H2D_REFINEMENT_H][2] = refinement.best_refinement_polynomial_order_type[H2D_REFINEMENT_H][3] = order; ElementToRefine::copy_orders(refinement.refinement_polynomial_order, refinement.best_refinement_polynomial_order_type[H2D_REFINEMENT_H]); return true; } break; case(noSelectionHP): { int max_allowed_order = this->max_order; if(this->max_order == H2DRS_DEFAULT_ORDER) max_allowed_order = H2DRS_MAX_ORDER; int order_h = H2D_GET_H_ORDER(order), order_v = H2D_GET_V_ORDER(order); int increased_order_h = std::min(max_allowed_order, order_h + 1), increased_order_v = std::min(max_allowed_order, order_v + 1); int increased_order; if(element->is_triangle()) increased_order = refinement.best_refinement_polynomial_order_type[H2D_REFINEMENT_H][0] = H2D_MAKE_QUAD_ORDER(increased_order_h, increased_order_h); else increased_order = refinement.best_refinement_polynomial_order_type[H2D_REFINEMENT_H][0] = H2D_MAKE_QUAD_ORDER(increased_order_h, increased_order_v); refinement.split = H2D_REFINEMENT_H; refinement.best_refinement_polynomial_order_type[H2D_REFINEMENT_H][0] = refinement.best_refinement_polynomial_order_type[H2D_REFINEMENT_H][1] = refinement.best_refinement_polynomial_order_type[H2D_REFINEMENT_H][2] = refinement.best_refinement_polynomial_order_type[H2D_REFINEMENT_H][3] = increased_order; ElementToRefine::copy_orders(refinement.refinement_polynomial_order, refinement.best_refinement_polynomial_order_type[H2D_REFINEMENT_H]); return true; } case(hXORpSelectionBasedOnError): { //make an uniform order in a case of a triangle int order_h = H2D_GET_H_ORDER(order), order_v = H2D_GET_V_ORDER(order); int current_min_order, current_max_order; this->get_current_order_range(element, current_min_order, current_max_order); if(current_max_order < std::max(order_h, order_v)) current_max_order = std::max(order_h, order_v); int last_order_h = std::min(current_max_order, order_h + 1), last_order_v = std::min(current_max_order, order_v + 1); int last_order = H2D_MAKE_QUAD_ORDER(last_order_h, last_order_v); //build candidates. Hermes::vector<Cand> candidates; candidates.push_back(Cand(H2D_REFINEMENT_P, last_order)); candidates.push_back(Cand(H2D_REFINEMENT_H, order, order, order, order)); this->evaluate_cands_error(candidates, element, rsln); Cand* best_candidate = (candidates[0].error < candidates[1].error) ? &candidates[0] : &candidates[1]; Cand* best_candidates_specific_type[4]; best_candidates_specific_type[H2D_REFINEMENT_P] = &candidates[0]; best_candidates_specific_type[H2D_REFINEMENT_H] = &candidates[1]; best_candidates_specific_type[2] = NULL; best_candidates_specific_type[3] = NULL; //copy result to output refinement.split = best_candidate->split; ElementToRefine::copy_orders(refinement.refinement_polynomial_order, best_candidate->p); for(int i = 0; i < 4; i++) if(best_candidates_specific_type[i] != NULL) ElementToRefine::copy_orders(refinement.best_refinement_polynomial_order_type[i], best_candidates_specific_type[i]->p); ElementToRefine::copy_errors(refinement.errors, best_candidate->errors); //modify orders in a case of a triangle such that order_v is zero if(element->is_triangle()) for(int i = 0; i < H2D_MAX_ELEMENT_SONS; i++) refinement.refinement_polynomial_order[i] = H2D_MAKE_QUAD_ORDER(H2D_GET_H_ORDER(refinement.refinement_polynomial_order[i]), 0); return true; } default: H1ProjBasedSelector<complex>::select_refinement(element, order, rsln, refinement); return true; break; } }
void L2ProjBasedSelector<Scalar>::create_candidates(Element* e, int quad_order, int max_ha_quad_order, int max_p_quad_order) { int order_h = H2D_GET_H_ORDER(quad_order), order_v = H2D_GET_V_ORDER(quad_order); int max_p_order_h = H2D_GET_H_ORDER(max_p_quad_order), max_p_order_v = H2D_GET_V_ORDER(max_p_quad_order); int max_ha_order_h = H2D_GET_H_ORDER(max_ha_quad_order), max_ha_order_v = H2D_GET_V_ORDER(max_ha_quad_order); bool tri = e->is_triangle(); //clear list of candidates this->candidates.clear(); if (this->candidates.capacity() < H2DRS_ASSUMED_MAX_CANDS) this->candidates.reserve(H2DRS_ASSUMED_MAX_CANDS); //generate all P-candidates (start from intention of generating all possible candidates //and restrict it according to the given adapt-type) bool iso_p = false; int start_quad_order = quad_order; int last_quad_order = H2D_MAKE_QUAD_ORDER(std::min(max_p_order_h, order_h+H2DRS_MAX_ORDER_INC), std::min(max_p_order_v, order_v+H2DRS_MAX_ORDER_INC)); switch(this->cand_list) { case H2D_H_ISO: case H2D_H_ANISO: last_quad_order = start_quad_order; break; //no P-candidates except the original candidate case H2D_P_ISO: case H2D_HP_ISO: case H2D_HP_ANISO_H: iso_p = true; break; //iso change of orders } this->append_candidates_split(quad_order, last_quad_order, H2D_REFINEMENT_P, tri || iso_p); //generate all H-candidates iso_p = false; int start_order_h = std::max(this->current_min_order, (order_h+1) / 2), start_order_v = std::max(this->current_min_order, (order_v+1) / 2); start_quad_order = H2D_MAKE_QUAD_ORDER(start_order_h, start_order_v); last_quad_order = H2D_MAKE_QUAD_ORDER(std::min(max_ha_order_h, start_order_h + H2DRS_MAX_ORDER_INC), std::min(max_ha_order_v, start_order_v + H2DRS_MAX_ORDER_INC)); switch(this->cand_list) { case H2D_H_ISO: case H2D_H_ANISO: last_quad_order = start_quad_order = quad_order; break; //no only one candidate will be created case H2D_P_ISO: case H2D_P_ANISO: last_quad_order = -1; break; //no H-candidate will be generated case H2D_HP_ISO: case H2D_HP_ANISO_H: iso_p = true; break; //iso change of orders } this->append_candidates_split(start_quad_order, last_quad_order, H2D_REFINEMENT_H, tri || iso_p); //generate all ANISO-candidates if (!tri && e->iro_cache < 8 /** \todo Find and why is iro_cache compared with the number 8. What does the number 8 mean? */ && (this->cand_list == H2D_H_ANISO || this->cand_list == H2D_HP_ANISO_H || this->cand_list == H2D_HP_ANISO)) { iso_p = false; int start_quad_order_hz = H2D_MAKE_QUAD_ORDER(order_h, std::max(this->current_min_order, (order_v+1) / 2)); int last_quad_order_hz = H2D_MAKE_QUAD_ORDER(std::min(max_ha_order_h, order_h+H2DRS_MAX_ORDER_INC), std::min(order_v, H2D_GET_V_ORDER(start_quad_order)+H2DRS_MAX_ORDER_INC)); int start_quad_order_vt = H2D_MAKE_QUAD_ORDER(std::max(this->current_min_order, (order_h+1) / 2), order_v); int last_quad_order_vt = H2D_MAKE_QUAD_ORDER(std::min(order_h, H2D_GET_H_ORDER(start_quad_order)+H2DRS_MAX_ORDER_INC), std::min(max_ha_order_v, order_v+H2DRS_MAX_ORDER_INC)); switch(this->cand_list) { case H2D_H_ANISO: last_quad_order_hz = start_quad_order_hz = quad_order; last_quad_order_vt = start_quad_order_vt = quad_order; break; //only one candidate will be created case H2D_HP_ANISO_H: iso_p = true; break; //iso change of orders } if (iso_p) { //make orders uniform: take mininmum order since nonuniformity is caused by different handling of orders along directions int order = std::min(H2D_GET_H_ORDER(start_quad_order_hz), H2D_GET_V_ORDER(start_quad_order_hz)); start_quad_order_hz = H2D_MAKE_QUAD_ORDER(order, order); order = std::min(H2D_GET_H_ORDER(start_quad_order_vt), H2D_GET_V_ORDER(start_quad_order_vt)); start_quad_order_vt = H2D_MAKE_QUAD_ORDER(order, order); order = std::min(H2D_GET_H_ORDER(last_quad_order_hz), H2D_GET_V_ORDER(last_quad_order_hz)); last_quad_order_hz = H2D_MAKE_QUAD_ORDER(order, order); order = std::min(H2D_GET_H_ORDER(last_quad_order_vt), H2D_GET_V_ORDER(last_quad_order_vt)); last_quad_order_vt = H2D_MAKE_QUAD_ORDER(order, order); } this->append_candidates_split(start_quad_order_hz, last_quad_order_hz, H2D_REFINEMENT_ANISO_H, iso_p); this->append_candidates_split(start_quad_order_vt, last_quad_order_vt, H2D_REFINEMENT_ANISO_V, iso_p); } }
unsigned short OrderPermutator::get_quad_order() const { return H2D_MAKE_QUAD_ORDER(order_h, order_v); }