void OGProjection::project_global(Hermes::Tuple<Space *> spaces, Hermes::Tuple< std::pair<WeakForm::matrix_form_val_t, WeakForm::matrix_form_ord_t> > proj_biforms, Hermes::Tuple< std::pair<WeakForm::vector_form_val_t, WeakForm::vector_form_ord_t> > proj_liforms, Hermes::Tuple<MeshFunction*> source_meshfns, scalar* target_vec, MatrixSolverType matrix_solver) { _F_ unsigned int n = spaces.size(); unsigned int n_biforms = proj_biforms.size(); if (n_biforms == 0) error("Please use the simpler version of project_global with the argument Hermes::Tuple<ProjNormType> proj_norms if you do not provide your own projection norm."); if (n_biforms != proj_liforms.size()) error("Mismatched numbers of projection forms in project_global()."); if (n != n_biforms) error("Mismatched numbers of projected functions and projection forms in project_global()."); // This is needed since spaces may have their DOFs enumerated only locally // when they come here. int ndof = Space::assign_dofs(spaces); // Define projection weak form. WeakForm* proj_wf = new WeakForm(n); for (unsigned int i = 0; i < n; i++) { proj_wf->add_matrix_form(i, i, proj_biforms[i].first, proj_biforms[i].second); proj_wf->add_vector_form(i, proj_liforms[i].first, proj_liforms[i].second, HERMES_ANY, source_meshfns[i]); } project_internal(spaces, proj_wf, target_vec, matrix_solver); }
// Set Dirichlet boundary values. void ModuleBasic::set_dirichlet_values(const std::vector<int> &bdy_markers_dirichlet, const std::vector<double> &bdy_values_dirichlet) { Hermes::Tuple<int> tm; tm = bdy_markers_dirichlet; Hermes::Tuple<double> tv; tv = bdy_values_dirichlet; if (tm.size() != tv.size()) error("Mismatched numbers of Dirichlet boundary markers and values."); for (unsigned int i = 0; i < tm.size(); i++) this->bc_values.add_const(tm[i], tv[i]); }
Adapt::Adapt(Hermes::Tuple< Space* > spaces_, Hermes::Tuple<ProjNormType> proj_norms) : num_act_elems(-1), have_errors(false), have_coarse_solutions(false), have_reference_solutions(false) { // sanity check if (proj_norms.size() > 0 && spaces_.size() != proj_norms.size()) error("Mismatched numbers of spaces and projection types in Adapt::Adapt()."); this->num = spaces_.size(); // sanity checks error_if(this->num <= 0, "Too few components (%d), only %d supported.", this->num, H2D_MAX_COMPONENTS); error_if(this->num >= H2D_MAX_COMPONENTS, "Too many components (%d), only %d supported.", this->num, H2D_MAX_COMPONENTS); for (int i = 0; i < this->num; i++) { if (spaces_[i] == NULL) error("spaces[%d] is NULL in Adapt::Adapt().", i); this->spaces.push_back(spaces_[i]); } // reset values memset(errors, 0, sizeof(errors)); memset(form, 0, sizeof(form)); memset(ord, 0, sizeof(ord)); memset(sln, 0, sizeof(sln)); memset(rsln, 0, sizeof(rsln)); if (proj_norms.size() > 0) { for (int i = 0; i < this->num; i++) { switch (proj_norms[i]) { case HERMES_L2_NORM: form[i][i] = l2_form<double, scalar>; ord[i][i] = l2_form<Ord, Ord>; break; case HERMES_H1_NORM: form[i][i] = h1_form<double, scalar>; ord[i][i] = h1_form<Ord, Ord>; break; case HERMES_H1_SEMINORM: form[i][i] = h1_semi_form<double, scalar>; ord[i][i] = h1_semi_form<Ord, Ord>; break; case HERMES_HCURL_NORM: form[i][i] = hcurl_form<double, scalar>; ord[i][i] = hcurl_form<Ord, Ord>; break; case HERMES_HDIV_NORM: form[i][i] = hdiv_form<double, scalar>; ord[i][i] = hdiv_form<Ord, Ord>; break; default: error("Unknown projection type in Adapt::Adapt()."); } } } }
double error_total(double (*efn)(MeshFunction*, MeshFunction*, RefMap*, RefMap*), double (*nfn)(MeshFunction*, RefMap*), Hermes::Tuple<Solution*>& slns1, Hermes::Tuple<Solution*>& slns2 ) { double error = 0.0, norm = 0.0; for (unsigned int i=0; i < slns1.size(); i++) { error += sqr(calc_abs_error(efn, slns1[i], slns2[i])); if (nfn) norm += sqr(calc_norm(nfn, slns2[i])); } return (nfn ? sqrt(error/norm) : sqrt(error)); }
bool calc_errors(Hermes::Tuple<Solution* > left, Hermes::Tuple<Solution *> right, Hermes::Tuple<double> & err_abs, Hermes::Tuple<double> & norm_vals, double & err_abs_total, double & norm_total, double & err_rel_total, Hermes::Tuple<ProjNormType> norms) { bool default_norms = false; // Checks. if(left.size() != right.size()) return false; if (norms != Hermes::Tuple<ProjNormType>()) { if(left.size() != norms.size()) return false; } else default_norms = true; // Zero the resulting Tuples. err_abs.clear(); norm_vals.clear(); // Zero the sums. err_abs_total = 0; norm_total = 0; err_rel_total = 0; // Calculation. for(unsigned int i = 0; i < left.size(); i++) { err_abs.push_back(calc_abs_error(left[i], right[i], default_norms ? HERMES_H1_NORM : norms[i])); norm_vals.push_back(calc_norm(right[i], default_norms ? HERMES_H1_NORM : norms[i])); err_abs_total += err_abs[i] * err_abs[i]; norm_total += norm_vals[i] * norm_vals[i]; } err_abs_total = sqrt(err_abs_total); norm_total = sqrt(norm_total); err_rel_total = err_abs_total / norm_total * 100.; // Everything went well, return appropriate flag. return true; }
void OGProjection::project_internal(Hermes::Tuple<Space *> spaces, WeakForm* wf, scalar* target_vec, MatrixSolverType matrix_solver) { _F_ unsigned int n = spaces.size(); // sanity checks if (n <= 0 || n > 10) error("Wrong number of projected functions in project_internal()."); for (unsigned int i = 0; i < n; i++) if(spaces[i] == NULL) error("this->spaces[%d] == NULL in project_internal().", i); if (spaces.size() != n) error("Number of spaces must match number of projected functions in project_internal()."); // this is needed since spaces may have their DOFs enumerated only locally. int ndof = Space::assign_dofs(spaces); // Initialize DiscreteProblem. bool is_linear = true; DiscreteProblem* dp = new DiscreteProblem(wf, spaces, is_linear); SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); dp->assemble(matrix, rhs, false); // Calculate the coefficient vector. bool solved = solver->solve(); scalar* coeffs; if (solved) coeffs = solver->get_solution(); if (target_vec != NULL) for (int i=0; i<ndof; i++) target_vec[i] = coeffs[i]; delete solver; delete matrix; delete rhs; delete dp; delete wf; }
void OGProjection::project_global(Hermes::Tuple<Space *> spaces, Hermes::Tuple<Solution *> sols_src, Hermes::Tuple<Solution *> sols_dest, MatrixSolverType matrix_solver, Hermes::Tuple<ProjNormType> proj_norms) { _F_ scalar* target_vec = new scalar[Space::get_num_dofs(spaces)]; Hermes::Tuple<MeshFunction *> ref_slns_mf; for (unsigned int i = 0; i < sols_src.size(); i++) ref_slns_mf.push_back(static_cast<MeshFunction*>(sols_src[i])); OGProjection::project_global(spaces, ref_slns_mf, target_vec, matrix_solver, proj_norms); Solution::vector_to_solutions(target_vec, spaces, sols_dest); delete [] target_vec; }
bool Adapt::adapt(Hermes::Tuple<RefinementSelectors::Selector *> refinement_selectors, double thr, int strat, int regularize, double to_be_processed) { error_if(!have_errors, "element errors have to be calculated first, call Adapt::calc_err_est()."); error_if(refinement_selectors == Hermes::Tuple<RefinementSelectors::Selector *>(), "selector not provided"); if (spaces.size() != refinement_selectors.size()) error("Wrong number of refinement selectors."); TimePeriod cpu_time; //get meshes int max_id = -1; Mesh* meshes[H2D_MAX_COMPONENTS]; for (int j = 0; j < this->num; j++) { meshes[j] = this->spaces[j]->get_mesh(); rsln[j]->set_quad_2d(&g_quad_2d_std); rsln[j]->enable_transform(false); if (meshes[j]->get_max_element_id() > max_id) max_id = meshes[j]->get_max_element_id(); } //reset element refinement info AUTOLA2_OR(int, idx, max_id + 1, this->num + 1); for(int j = 0; j < max_id; j++) for(int l = 0; l < this->num; l++) idx[j][l] = -1; // element not refined double err0_squared = 1000.0; double processed_error_squared = 0.0; vector<ElementToRefine> elem_inx_to_proc; //list of indices of elements that are going to be processed elem_inx_to_proc.reserve(num_act_elems); //adaptivity loop double error_squared_threshod = -1; //an error threshold that breaks the adaptivity loop in a case of strategy 1 int num_exam_elem = 0; //a number of examined elements int num_ignored_elem = 0; //a number of ignored elements int num_not_changed = 0; //a number of element that were not changed int num_priority_elem = 0; //a number of elements that were processed using priority queue bool first_regular_element = true; //true if first regular element was not processed yet int inx_regular_element = 0; while (inx_regular_element < num_act_elems || !priority_queue.empty()) { int id, comp, inx_element; //get element identification if (priority_queue.empty()) { id = regular_queue[inx_regular_element].id; comp = regular_queue[inx_regular_element].comp; inx_element = inx_regular_element; inx_regular_element++; } else { id = priority_queue.front().id; comp = priority_queue.front().comp; inx_element = -1; priority_queue.pop(); num_priority_elem++; } num_exam_elem++; //get info linked with the element double err_squared = errors[comp][id]; Mesh* mesh = meshes[comp]; Element* e = mesh->get_element(id); if (!should_ignore_element(inx_element, mesh, e)) { //check if adaptivity loop should end if (inx_element >= 0) { //prepare error threshold for strategy 1 if (first_regular_element) { error_squared_threshod = thr * err_squared; first_regular_element = false; } // first refinement strategy: // refine elements until prescribed amount of error is processed // if more elements have similar error refine all to keep the mesh symmetric if ((strat == 0) && (processed_error_squared > sqrt(thr) * errors_squared_sum) && fabs((err_squared - err0_squared)/err0_squared) > 1e-3) break; // second refinement strategy: // refine all elements whose error is bigger than some portion of maximal error if ((strat == 1) && (err_squared < error_squared_threshod)) break; if ((strat == 2) && (err_squared < thr)) break; if ((strat == 3) && ( (err_squared < error_squared_threshod) || ( processed_error_squared > 1.5 * to_be_processed )) ) break; } // get refinement suggestion ElementToRefine elem_ref(id, comp); int current = this->spaces[comp]->get_element_order(id); bool refined = refinement_selectors[comp]->select_refinement(e, current, rsln[comp], elem_ref); //add to a list of elements that are going to be refined if (can_refine_element(mesh, e, refined, elem_ref) ) { idx[id][comp] = (int)elem_inx_to_proc.size(); elem_inx_to_proc.push_back(elem_ref); err0_squared = err_squared; processed_error_squared += err_squared; } else { debug_log("Element (id:%d, comp:%d) not changed", e->id, comp); num_not_changed++; } } else { num_ignored_elem++; } } verbose("Examined elements: %d", num_exam_elem); verbose(" Elements taken from priority queue: %d", num_priority_elem); verbose(" Ignored elements: %d", num_ignored_elem); verbose(" Not changed elements: %d", num_not_changed); verbose(" Elements to process: %d", elem_inx_to_proc.size()); bool done = false; if (num_exam_elem == 0) done = true; else if (elem_inx_to_proc.empty()) { warn("None of the elements selected for refinement could be refined. Adaptivity step not successful, returning 'true'."); done = true; } //fix refinement if multimesh is used fix_shared_mesh_refinements(meshes, elem_inx_to_proc, idx, refinement_selectors); //apply refinements apply_refinements(elem_inx_to_proc); // in singlemesh case, impose same orders across meshes homogenize_shared_mesh_orders(meshes); // mesh regularization if (regularize >= 0) { if (regularize == 0) { regularize = 1; warn("Total mesh regularization is not supported in adaptivity. 1-irregular mesh is used instead."); } for (int i = 0; i < this->num; i++) { int* parents; parents = meshes[i]->regularize(regularize); this->spaces[i]->distribute_orders(meshes[i], parents); delete [] parents; } } for (int j = 0; j < this->num; j++) rsln[j]->enable_transform(true); verbose("Refined elements: %d", elem_inx_to_proc.size()); report_time("Refined elements in: %g s", cpu_time.tick().last()); //store for the user to retrieve last_refinements.swap(elem_inx_to_proc); have_errors = false; if (strat == 2 && done == true) have_errors = true; // space without changes // since space changed, assign dofs: Space::assign_dofs(this->spaces); return done; }
void OGProjection::project_global(Hermes::Tuple<Space *> spaces, Hermes::Tuple<MeshFunction*> source_meshfns, scalar* target_vec, MatrixSolverType matrix_solver, Hermes::Tuple<ProjNormType> proj_norms) { _F_ int n = spaces.size(); // define temporary projection weak form WeakForm* proj_wf = new WeakForm(n); int found[100]; for (int i = 0; i < 100; i++) found[i] = 0; for (int i = 0; i < n; i++) { int norm; if (proj_norms == Hermes::Tuple<ProjNormType>()) { ESpaceType space_type = spaces[i]->get_type(); switch (space_type) { case HERMES_H1_SPACE: norm = HERMES_H1_NORM; break; case HERMES_HCURL_SPACE: norm = HERMES_HCURL_NORM; break; case HERMES_HDIV_SPACE: norm = HERMES_HDIV_NORM; break; case HERMES_L2_SPACE: norm = HERMES_L2_NORM; break; default: error("Unknown space type in OGProjection::project_global()."); } } else norm = proj_norms[i]; if (norm == HERMES_H1_NORM) { found[i] = 1; proj_wf->add_matrix_form(i, i, H1projection_biform<double, scalar>, H1projection_biform<Ord, Ord>); proj_wf->add_vector_form(i, H1projection_liform<double, scalar>, H1projection_liform<Ord, Ord>, HERMES_ANY, source_meshfns[i]); } if (norm == HERMES_H1_SEMINORM) { found[i] = 1; proj_wf->add_matrix_form(i, i, H1_semi_projection_biform<double, scalar>, H1_semi_projection_biform<Ord, Ord>); proj_wf->add_vector_form(i, H1_semi_projection_liform<double, scalar>, H1_semi_projection_liform<Ord, Ord>, HERMES_ANY, source_meshfns[i]); } if (norm == HERMES_HCURL_NORM) { found[i] = 1; proj_wf->add_matrix_form(i, i, Hcurlprojection_biform<double, scalar>, Hcurlprojection_biform<Ord, Ord>); proj_wf->add_vector_form(i, Hcurlprojection_liform<double, scalar>, Hcurlprojection_liform<Ord, Ord>, HERMES_ANY, source_meshfns[i]); } if (norm == HERMES_HDIV_NORM) { found[i] = 1; proj_wf->add_matrix_form(i, i, Hdivprojection_biform<double, scalar>, Hdivprojection_biform<Ord, Ord>); proj_wf->add_vector_form(i, Hdivprojection_liform<double, scalar>, Hdivprojection_liform<Ord, Ord>, HERMES_ANY, source_meshfns[i]); } if (norm == HERMES_L2_NORM) { found[i] = 1; proj_wf->add_matrix_form(i, i, L2projection_biform<double, scalar>, L2projection_biform<Ord, Ord>); proj_wf->add_vector_form(i, L2projection_liform<double, scalar>, L2projection_liform<Ord, Ord>, HERMES_ANY, source_meshfns[i]); } } for (int i=0; i < n; i++) { if (found[i] == 0) { warn("index of component: %d\n", i); error("Wrong projection norm in project_global()."); } } project_internal(spaces, proj_wf, target_vec, matrix_solver); }