16 #include "exact_solution.h"
19 #include "ogprojection.h"
21 #include "algebra/dense_matrix_operations.h"
22 #include "util/memory_handling.h"
28 static double3* cheb_tab_tri[11];
29 static double3* cheb_tab_quad[11];
30 static unsigned char cheb_np_tri[11];
31 static unsigned char cheb_np_quad[11];
33 static double3** cheb_tab[2] = { cheb_tab_tri, cheb_tab_quad };
34 static unsigned char* cheb_np[2] = { cheb_np_tri, cheb_np_quad };
36 static class Quad2DCheb :
public Quad2D
42 max_order[0] = max_order[1] = 10;
43 num_tables[0] = num_tables[1] = 11;
47 tables[0][0] = tables[1][0] =
nullptr;
48 np[0][0] = np[1][0] = 0;
52 for (
int mode_i = 0; mode_i <= 1; mode_i++)
54 for (k = 0; k <= 10; k++)
56 np[mode_i][k] = n = mode_i ? sqr(k + 1) : (k + 1)*(k + 2) / 2;
57 tables[mode_i][k] = pt = malloc_with_check<double3>(n);
59 for (i = k, m = 0; i >= 0; i--)
60 for (j = k; j >= (mode_i ? 0 : k - i); j--, m++) {
61 pt[m][0] = k ? cos(j * M_PI / k) : 1.0;
62 pt[m][1] = k ? cos(i * M_PI / k) : 1.0;
71 for (
int mode_i = 0; mode_i <= 1; mode_i++)
72 for (
int k = 1; k <= 10; k++)
73 free_with_check(tables[mode_i][k]);
76 virtual unsigned char get_id()
81 virtual void dummy_fn() {}
84 template<
typename Scalar>
85 void Solution<Scalar>::set_static_verbose_output(
bool verbose)
87 Solution<Scalar>::static_verbose_output = verbose;
90 template<
typename Scalar>
91 bool Solution<Scalar>::static_verbose_output =
false;
93 template<
typename Scalar>
97 sln_type = HERMES_UNDEF;
98 this->num_components = 0;
100 mono_coeffs =
nullptr;
101 elem_coeffs[0] = elem_coeffs[1] =
nullptr;
102 elem_orders =
nullptr;
103 dxdy_buffer =
nullptr;
104 num_coeffs = num_elems = 0;
107 this->set_quad_2d(&g_quad_2d_std);
114 space_type = HERMES_INVALID_SPACE;
119 Solution<std::complex<double> >::Solution()
120 : MeshFunction<
std::complex<double> >()
122 space_type = HERMES_INVALID_SPACE;
127 Solution<double>::Solution(MeshSharedPtr mesh) : MeshFunction<double>(mesh)
129 space_type = HERMES_INVALID_SPACE;
135 Solution<std::complex<double> >::Solution(MeshSharedPtr mesh) : MeshFunction<
std::complex<double> >(mesh)
137 space_type = HERMES_INVALID_SPACE;
143 Solution<double>::Solution(SpaceSharedPtr<double> s, Vector<double>* coeff_vec) : MeshFunction<double>(s->get_mesh())
145 space_type = s->get_type();
147 this->mesh = s->get_mesh();
148 Solution<double>::vector_to_solution(coeff_vec, s,
this);
152 Solution<std::complex<double> >::Solution(SpaceSharedPtr<std::complex<double> > s, Vector<std::complex<double> >* coeff_vec) : MeshFunction<
std::complex<double> >(s->get_mesh())
154 space_type = s->get_type();
156 this->mesh = s->get_mesh();
157 Solution<std::complex<double> >::vector_to_solution(coeff_vec, s,
this);
161 Solution<double>::Solution(SpaceSharedPtr<double> s,
double* coeff_vec) : MeshFunction<double>(s->get_mesh())
163 space_type = s->get_type();
165 this->mesh = s->get_mesh();
166 Solution<double>::vector_to_solution(coeff_vec, s,
this);
170 Solution<std::complex<double> >::Solution(SpaceSharedPtr<std::complex<double> > s, std::complex<double> * coeff_vec) : MeshFunction<
std::complex<double> >(s->get_mesh())
172 space_type = s->get_type();
174 this->mesh = s->get_mesh();
175 Solution<std::complex<double> >::vector_to_solution(coeff_vec, s,
this);
178 template<
typename Scalar>
182 if (solution ==
nullptr)
183 throw Exceptions::Exception(
"The instance is in fact not a Solution instance in copy().");
185 if (solution->sln_type == HERMES_UNDEF)
186 throw Hermes::Exceptions::Exception(
"Solution being copied is uninitialized.");
189 this->mesh = solution->mesh;
191 sln_type = solution->sln_type;
192 space_type = solution->get_space_type();
194 num_dofs = solution->num_dofs;
196 if (solution->sln_type == HERMES_SLN)
198 num_coeffs = solution->num_coeffs;
199 num_elems = solution->num_elems;
200 mono_coeffs = malloc_with_check<Solution<Scalar>, Scalar>(num_coeffs,
this);
201 memcpy(mono_coeffs, solution->
mono_coeffs,
sizeof(Scalar)* num_coeffs);
203 for (
int l = 0; l < this->num_components; l++)
205 elem_coeffs[l] = malloc_with_check<Solution<Scalar>,
int>(num_elems,
this);
206 memcpy(elem_coeffs[l], solution->
elem_coeffs[l],
sizeof(
int)* num_elems);
209 elem_orders = malloc_with_check<Solution<Scalar>,
int>(num_elems,
this);
210 memcpy(elem_orders, solution->
elem_orders,
sizeof(
int)* num_elems);
214 throw Hermes::Exceptions::Exception(
"Undefined or exact solutions cannot be copied into an instance of Solution already coming from computation.");
216 this->element =
nullptr;
219 template<
typename Scalar>
227 template<
typename Scalar>
230 free_with_check(mono_coeffs);
231 free_with_check(elem_orders);
232 free_with_check(dxdy_buffer);
234 for (
int i = 0; i < this->num_components; i++)
235 free_with_check(elem_coeffs[i]);
237 space_type = HERMES_INVALID_SPACE;
240 template<
typename Scalar>
251 unsigned char* perm[2][11];
255 for (
int m = 0; m <= 1; m++)
257 for (
int i = 0; i <= 10; i++)
260 perm[m][i] =
nullptr;
267 for (
int m = 0; m <= 1; m++)
269 for (
int i = 0; i <= 10; i++)
271 free_with_check(mat[m][i],
true);
272 free_with_check(perm[m][i]);
279 template<
typename Scalar>
282 if (mono_lu.mat[mode][o] ==
nullptr)
284 unsigned char i, j, m, row;
287 unsigned char n = this->mode ? sqr(o + 1) : (o + 1)*(o + 2) / 2;
290 mono_lu.mat[mode][o] = new_matrix<double>(n, n);
291 for (k = o, row = 0; k >= 0; k--)
293 y = o ? cos(k * M_PI / o) : 1.0;
294 for (l = o; l >= (this->mode ? 0 : o - k); l--, row++)
296 x = o ? cos(l * M_PI / o) : 1.0;
299 for (i = 0, yn = 1.0, m = n - 1; i <= o; i++, yn *= y)
300 for (j = (this->mode ? 0 : i), xn = 1.0; j <= o; j++, xn *= x, m--)
301 mono_lu.mat[mode][o][row][m] = xn * yn;
306 if (mono_lu.perm[mode][o] ==
nullptr)
307 mono_lu.perm[mode][o] = malloc_with_check<Solution<Scalar>,
unsigned char>(n,
this);
308 ludcmp(mono_lu.mat[mode][o], n, mono_lu.perm[mode][o], &d);
311 return mono_lu.mat[mode][o];
314 template<
typename Scalar>
319 throw Exceptions::NullException(2);
321 space_type = space->get_type();
322 Scalar* coeffs = malloc_with_check<Solution<Scalar>, Scalar>(vec->get_size(),
this);
323 vec->extract(coeffs);
324 this->set_coeff_vector(space, coeffs, add_dir_lift, start_index);
325 free_with_check(coeffs);
328 template<
typename Scalar>
330 const Scalar* coeff_vec,
bool add_dir_lift,
int start_index)
334 if (Solution<Scalar>::static_verbose_output)
335 Hermes::Mixins::Loggable::Static::info(
"Solution: set_coeff_vector called.");
338 if (space->get_mesh() ==
nullptr)
339 throw Exceptions::Exception(
"Mesh == nullptr in Solution<Scalar>::set_coeff_vector().");
340 Helpers::check_for_null(space->get_mesh());
341 Helpers::check_for_null(coeff_vec);
343 if (!space->is_up_to_date())
344 throw Exceptions::Exception(
"Provided 'space' is not up to date.");
346 if (Solution<Scalar>::static_verbose_output)
347 Hermes::Mixins::Loggable::Static::info(
"Solution: set_coeff_vector - solution being freed.");
351 this->space_type = space->get_type();
352 this->num_components = pss.get_num_components();
353 this->sln_type = HERMES_SLN;
354 this->mesh = space->get_mesh();
357 num_elems = this->mesh->get_max_element_id();
358 free_with_check(elem_orders);
359 elem_orders = calloc_with_check<Solution<Scalar>,
int>(num_elems,
this);
360 for (
int l = 0; l < this->num_components; l++)
362 free_with_check(elem_coeffs[l]);
363 elem_coeffs[l] = calloc_with_check<Solution<Scalar>,
int>(num_elems,
this);
370 for_all_active_elements(e, this->mesh)
372 this->mode = e->get_mode();
373 o = space->get_element_order(e->id);
375 for (
unsigned int k = 0; k < e->get_nvert(); k++)
377 int eo = space->get_edge_order(e, k);
383 if (space->shapeset->get_num_components() == 2)
384 if (o < space->shapeset->get_max_order())
387 num_coeffs += this->mode ? sqr(o + 1) : (o + 1)*(o + 2) / 2;
388 elem_orders[e->id] = o;
390 num_coeffs *= this->num_components;
391 free_with_check(mono_coeffs);
392 mono_coeffs = malloc_with_check<Solution<Scalar>, Scalar>(num_coeffs,
this);
395 Quad2D* quad = &g_quad_2d_cheb;
396 pss.set_quad_2d(quad);
397 Scalar* mono = mono_coeffs;
398 for_all_active_elements(e, this->mesh)
400 this->mode = e->get_mode();
401 o = elem_orders[e->id];
402 unsigned char np = quad->get_num_points(o, e->get_mode());
405 space->get_element_assembly_list(e, &al);
406 pss.set_active_element(e);
408 for (
int l = 0; l < this->num_components; l++)
412 elem_coeffs[l][e->id] = (int)(mono - mono_coeffs);
413 memset(val, 0,
sizeof(Scalar)*np);
414 for (
unsigned int k = 0; k < al.cnt; k++)
416 pss.set_active_shape(al.idx[k]);
419 double dir_lift_coeff = add_dir_lift ? 1.0 : 0.0;
423 Scalar coef = al.coef[k] * (dof >= 0 ? coeff_vec[dof - space->first_dof + start_index] : dir_lift_coeff);
424 const double* shape = pss.get_fn_values(l);
425 for (
int i = 0; i < np; i++)
426 val[i] += shape[i] * coef;
431 calc_mono_matrix(this->mode, o);
432 lubksb(mono_lu.mat[this->mode][o], np, mono_lu.perm[this->mode][o], val);
437 this->element =
nullptr;
438 if (Solution<Scalar>::static_verbose_output)
439 Hermes::Mixins::Loggable::Static::info(
"Solution: set_coeff_vector - done.");
442 template<
typename Scalar>
445 std::vector<bool> add_dir_lift, std::vector<int> start_indices)
447 Helpers::check_for_null(solution_vector);
448 Helpers::check_length(solutions, spaces);
451 std::vector<int> start_indices_new;
452 if (start_indices.empty())
455 for (
unsigned char i = 0; i < spaces.size(); i++)
457 start_indices_new.push_back(counter);
458 counter += spaces[i]->get_num_dofs();
463 if (start_indices.size() != spaces.size())
throw Hermes::Exceptions::Exception(
"Mismatched start indices in vector_to_solutions().");
464 for (
unsigned char i = 0; i < spaces.size(); i++)
466 start_indices_new.push_back(start_indices[i]);
470 for (
unsigned char i = 0; i < spaces.size(); i++)
472 if (Solution<Scalar>::static_verbose_output)
473 Hermes::Mixins::Loggable::Static::info(
"Vector to Solution: %d-th solution", i);
475 if (add_dir_lift == std::vector<bool>())
482 template<
typename Scalar>
486 Helpers::check_for_null(solution_vector);
487 solution->
set_coeff_vector(space, solution_vector, add_dir_lift, start_index);
490 template<
typename Scalar>
491 void Solution<Scalar>::vector_to_solution(
const Scalar* solution_vector, SpaceSharedPtr<Scalar> space,
492 MeshFunctionSharedPtr<Scalar> solution,
bool add_dir_lift,
int start_index)
494 Helpers::check_for_null(solution_vector);
496 Solution<Scalar>* sln =
dynamic_cast<Solution<Scalar>*
>(solution.get());
498 throw Exceptions::Exception(
"Passed solution is in fact not a Solution instance in vector_to_solution().");
500 sln->set_coeff_vector(space, solution_vector, add_dir_lift, start_index);
503 template<
typename Scalar>
505 std::vector<MeshFunctionSharedPtr<Scalar> > solutions, std::vector<bool> add_dir_lift, std::vector<int> start_indices)
507 Helpers::check_for_null(solution_vector);
508 Helpers::check_length(solutions, spaces);
511 std::vector<int> start_indices_new;
512 if (start_indices.empty())
515 for (
unsigned char i = 0; i < spaces.size(); i++)
517 start_indices_new.push_back(counter);
518 counter += spaces[i]->get_num_dofs();
523 if (start_indices.size() != spaces.size())
throw Hermes::Exceptions::Exception(
"Mismatched start indices in vector_to_solutions().");
524 for (
unsigned char i = 0; i < spaces.size(); i++)
526 start_indices_new.push_back(start_indices[i]);
530 for (
unsigned char i = 0; i < spaces.size(); i++)
532 if (Solution<Scalar>::static_verbose_output)
533 Hermes::Mixins::Loggable::Static::info(
"Vector to Solution: %d-th solution", i);
535 if (add_dir_lift == std::vector<bool>())
536 Solution<Scalar>::vector_to_solution(solution_vector, spaces[i], solutions[i],
true, start_indices_new[i]);
538 Solution<Scalar>::vector_to_solution(solution_vector, spaces[i], solutions[i], add_dir_lift[i], start_indices_new[i]);
542 template<
typename Scalar>
543 void Solution<Scalar>::vector_to_solutions_common_dir_lift(
const Vector<Scalar>* solution_vector, std::vector<SpaceSharedPtr<Scalar> > spaces,
544 std::vector<MeshFunctionSharedPtr<Scalar> > solutions,
bool add_dir_lift)
546 Helpers::check_for_null(solution_vector);
547 Helpers::check_length(spaces, solutions);
550 std::vector<int> start_indices_new;
552 for (
unsigned char i = 0; i < spaces.size(); i++)
554 start_indices_new.push_back(counter);
555 counter += spaces[i]->get_num_dofs();
558 for (
unsigned char i = 0; i < spaces.size(); i++)
560 if (Solution<Scalar>::static_verbose_output)
561 Hermes::Mixins::Loggable::Static::info(
"Vector to Solution: %d-th solution", i);
563 Solution<Scalar>::vector_to_solution(solution_vector, spaces[i], solutions[i], add_dir_lift, start_indices_new[i]);
567 template<
typename Scalar>
568 void Solution<Scalar>::vector_to_solutions_common_dir_lift(
const Scalar* solution_vector, std::vector<SpaceSharedPtr<Scalar> > spaces,
569 std::vector<MeshFunctionSharedPtr<Scalar> > solutions,
bool add_dir_lift)
571 Helpers::check_for_null(solution_vector);
572 Helpers::check_length(solutions, spaces);
575 std::vector<int> start_indices_new;
577 for (
unsigned char i = 0; i < spaces.size(); i++)
579 start_indices_new.push_back(counter);
580 counter += spaces[i]->get_num_dofs();
583 for (
unsigned char i = 0; i < spaces.size(); i++)
585 if (Solution<Scalar>::static_verbose_output)
586 Hermes::Mixins::Loggable::Static::info(
"Vector to Solution: %d-th solution", i);
588 Solution<Scalar>::vector_to_solution(solution_vector, spaces[i], solutions[i], add_dir_lift, start_indices_new[i]);
592 template<
typename Scalar>
593 void Solution<Scalar>::vector_to_solution(
const Vector<Scalar>* solution_vector, SpaceSharedPtr<Scalar> space,
594 MeshFunctionSharedPtr<Scalar> solution,
bool add_dir_lift,
int start_index)
597 Helpers::check_for_null(solution_vector);
599 Solution<Scalar>* sln =
dynamic_cast<Solution<Scalar>*
>(solution.get());
601 throw Exceptions::Exception(
"Passed solution is in fact not a Solution instance in vector_to_solution().");
603 sln->set_coeff_vector(space, solution_vector, add_dir_lift, start_index);
606 template<
typename Scalar>
609 space_type = space->get_type();
610 int ndof = space->get_num_dofs();
611 Scalar *temp = malloc_with_check<Solution<Scalar>, Scalar>(ndof,
this);
612 memset(temp, 0,
sizeof(Scalar)*ndof);
613 bool add_dir_lift =
true;
615 this->set_coeff_vector(space, temp, add_dir_lift, start_index);
616 free_with_check(temp);
619 template<
typename Scalar>
622 if (transform != enable)
623 this->invalidate_values();
627 template<
typename Scalar>
630 Scalar* base_vector = malloc_with_check<Solution<Scalar>, Scalar>(target_space->get_num_dofs(),
this);
631 Scalar* added_vector = malloc_with_check<Solution<Scalar>, Scalar>(target_space->get_num_dofs(),
this);
635 for (
int i = 0; i < target_space->get_num_dofs(); i++)
636 base_vector[i] += added_vector[i];
638 this->set_coeff_vector(target_space, base_vector,
true, 0);
641 template<
typename Scalar>
644 if (sln_type == HERMES_SLN)
646 for (
int i = 0; i < num_coeffs; i++)
647 mono_coeffs[i] *= coef;
649 else if (sln_type == HERMES_EXACT)
652 throw Hermes::Exceptions::Exception(
"Uninitialized solution.");
655 template<
typename Scalar>
659 for (i = 0; i <= o; i++)
663 for (j = 0; j < k; j++)
664 *result++ = (Scalar)(k - j) * mono[j];
669 template<
typename Scalar>
670 void Solution<Scalar>::make_dy_coeffs(
int mode,
int o, Scalar* mono, Scalar* result)
675 for (j = 0; j <= o; j++)
677 for (i = 0; i < o; i++)
678 for (j = 0; j <= o; j++)
679 *result++ = (Scalar)(o - i) * (*mono++);
682 for (i = 0; i <= o; i++)
685 for (j = 0; j < i; j++)
686 *result++ = (Scalar)(o + 1 - i) * (*mono++);
691 template<
typename Scalar>
692 void Solution<Scalar>::init_dxdy_buffer()
694 free_with_check(dxdy_buffer);
695 dxdy_buffer = malloc_with_check<Solution<Scalar>, Scalar>(this->num_components * 5 * 121,
this);
698 template<
typename Scalar>
703 if (sln_type == HERMES_SLN)
705 int o = this->order = elem_orders[this->element->id];
706 int n = this->mode ? sqr(o + 1) : (o + 1)*(o + 2) / 2;
708 for (
int i = 0, m = 0; i < this->num_components; i++)
710 Scalar* mono = mono_coeffs + elem_coeffs[i][e->
id];
711 dxdy_coeffs[i][0] = mono;
713 make_dx_coeffs(this->mode, o, mono, dxdy_coeffs[i][1] = dxdy_buffer + m); m += n;
714 make_dy_coeffs(this->mode, o, mono, dxdy_coeffs[i][2] = dxdy_buffer + m); m += n;
715 #ifdef H2D_USE_SECOND_DERIVATIVES
716 make_dx_coeffs(this->mode, o, dxdy_coeffs[i][1], dxdy_coeffs[i][3] = dxdy_buffer + m); m += n;
717 make_dy_coeffs(this->mode, o, dxdy_coeffs[i][2], dxdy_coeffs[i][4] = dxdy_buffer + m); m += n;
718 make_dx_coeffs(this->mode, o, dxdy_coeffs[i][2], dxdy_coeffs[i][5] = dxdy_buffer + m); m += n;
722 else if (sln_type == HERMES_EXACT)
729 throw Hermes::Exceptions::Exception(
"Uninitialized solution.");
732 template<
typename Scalar>
733 static inline void set_vec_num(
int n, Scalar* y, Scalar num)
735 for (
int i = 0; i < n; i++)
739 template<
typename Scalar>
740 static inline void vec_x_vec_p_num(
int n, Scalar* y, Scalar* x, Scalar num)
742 for (
int i = 0; i < n; i++)
743 y[i] = y[i] * x[i] + num;
746 template<
typename Scalar>
747 static inline void vec_x_vec_p_vec(
int n, Scalar* y, Scalar* x, Scalar* z)
749 for (
int i = 0; i < n; i++)
750 y[i] = y[i] * x[i] + z[i];
753 template<
typename Scalar>
754 void Solution<Scalar>::transform_values(
int order,
int mask,
int np)
760 if ((space_type == HERMES_H1_SPACE) || (space_type == HERMES_L2_SPACE))
762 #ifdef H2D_USE_SECOND_DERIVATIVES
763 if ((newmask & H2D_SECOND) == H2D_SECOND)
765 this->update_refmap();
766 mat = this->refmap.get_inv_ref_map(order);
767 double3x2 *mm, *mat2 = this->refmap.get_second_ref_map(order);
768 for (i = 0, m = mat, mm = mat2; i < np; i++, m++, mm++)
770 Scalar vx = this->values[0][1][i];
771 Scalar vy = this->values[0][2][i];
772 Scalar vxx = this->values[0][3][i];
773 Scalar vyy = this->values[0][4][i];
774 Scalar vxy = this->values[0][5][i];
777 this->values[0][3][i] = sqr((*m)[0][0])*vxx + 2 * (*m)[0][1] * (*m)[0][0] * vxy + sqr((*m)[0][1])*vyy + (*mm)[0][0] * vx + (*mm)[0][1] * vy;
779 this->values[0][4][i] = sqr((*m)[1][0])*vxx + 2 * (*m)[1][1] * (*m)[1][0] * vxy + sqr((*m)[1][1])*vyy + (*mm)[2][0] * vx + (*mm)[2][1] * vy;
781 this->values[0][5][i] = (*m)[0][0] * (*m)[1][0] * vxx + ((*m)[0][0] * (*m)[1][1] + (*m)[1][0] * (*m)[0][1])*vxy + (*m)[0][1] * (*m)[1][1] * vyy + (*mm)[1][0] * vx + (*mm)[1][1] * vy;
785 if ((mask & H2D_GRAD) == H2D_GRAD)
787 this->update_refmap();
788 mat = this->refmap.get_const_inv_ref_map();
789 if (!this->refmap.is_jacobian_const()) { mat = this->refmap.get_inv_ref_map(order); mstep = 1; }
791 for (i = 0, m = mat; i < np; i++, m += mstep)
793 Scalar vx = this->values[0][1][i];
794 Scalar vy = this->values[0][2][i];
795 this->values[0][1][i] = (*m)[0][0] * vx + (*m)[0][1] * vy;
796 this->values[0][2][i] = (*m)[1][0] * vx + (*m)[1][1] * vy;
802 else if (space_type == HERMES_HCURL_SPACE)
804 this->update_refmap();
805 mat = this->refmap.get_const_inv_ref_map();
806 if (!this->refmap.is_jacobian_const()) { mat = this->refmap.get_inv_ref_map(order); mstep = 1; }
808 for (i = 0, m = mat; i < np; i++, m += mstep)
812 Scalar vx = this->values[0][0][i];
813 Scalar vy = this->values[1][0][i];
814 this->values[0][0][i] = (*m)[0][0] * vx + (*m)[0][1] * vy;
815 this->values[1][0][i] = (*m)[1][0] * vx + (*m)[1][1] * vy;
817 if ((mask & H2D_CURL) == H2D_CURL)
819 Scalar e0x = this->values[0][1][i], e0y = this->values[0][2][i];
820 Scalar e1x = this->values[1][1][i], e1y = this->values[1][2][i];
821 this->values[1][1][i] = (*m)[0][0] * ((*m)[1][0] * e0x + (*m)[1][1] * e1x) + (*m)[0][1] * ((*m)[1][0] * e0y + (*m)[1][1] * e1y);
822 this->values[0][2][i] = (*m)[1][0] * ((*m)[0][0] * e0x + (*m)[0][1] * e1x) + (*m)[1][1] * ((*m)[0][0] * e0y + (*m)[0][1] * e1y);
828 else if (space_type == HERMES_HDIV_SPACE)
832 this->update_refmap();
833 mat = this->refmap.get_const_inv_ref_map();
834 if (!this->refmap.is_jacobian_const()) { mat = this->refmap.get_inv_ref_map(order); mstep = 1; }
836 for (i = 0, m = mat; i < np; i++, m += mstep)
838 Scalar vx = this->values[0][0][i];
839 Scalar vy = this->values[1][0][i];
840 this->values[0][0][i] = (*m)[1][1] * vx - (*m)[1][0] * vy;
841 this->values[1][0][i] = -(*m)[0][1] * vx + (*m)[0][0] * vy;
847 template<
typename Scalar>
851 Quad2D* quad = this->quads[this->cur_quad];
852 unsigned char np = quad->get_num_points(order, this->mode);
854 if (sln_type == HERMES_SLN)
860 if (this->num_components == 1)
862 if ((mask & H2D_FN_DX_0) || (mask & H2D_FN_DY_0)) mask |= H2D_GRAD;
863 #ifdef H2D_USE_SECOND_DERIVATIVES
864 if ((mask & H2D_FN_DXX_0) || (mask & H2D_FN_DXY_0) || (mask & H2D_FN_DYY_0)) mask |= H2D_SECOND;
868 else if (space_type == HERMES_HCURL_SPACE)
870 if ((mask & H2D_FN_VAL_0) || (mask & H2D_FN_VAL_1)) mask |=
H2D_FN_VAL;
871 if ((mask & H2D_FN_DX_1) || (mask & H2D_FN_DY_0)) mask |= H2D_CURL;
876 if ((mask & H2D_FN_VAL_0) || (mask & H2D_FN_VAL_1)) mask |=
H2D_FN_VAL;
881 double3* pt = quad->get_points(order, this->element->get_mode());
882 for (i = 0; i < np; i++)
884 x[i] = pt[i][0] * this->ctm->m[0] + this->ctm->t[0];
885 y[i] = pt[i][1] * this->ctm->m[1] + this->ctm->t[1];
889 int o = elem_orders[this->element->id];
890 for (l = 0; l < this->num_components; l++)
892 for (k = 0; k < H2D_NUM_FUNCTION_VALUES; k++)
894 if (mask & this->idx2mask[k][l])
896 Scalar* result = this->values[l][k];
899 Scalar* mono = dxdy_coeffs[l][k];
900 for (i = 0; i <= o; i++)
902 set_vec_num(np, tx, *mono++);
903 for (j = 1; j <= (this->mode ? o : i); j++)
904 vec_x_vec_p_num(np, tx, x, *mono++);
907 memcpy(result, tx,
sizeof(Scalar)*np);
909 vec_x_vec_p_vec(np, result, y, tx);
917 transform_values(order, mask, np);
919 else if (sln_type == HERMES_EXACT)
922 throw Hermes::Exceptions::Exception(
"Cannot obtain second derivatives of an exact solution.");
924 this->update_refmap();
925 double* x = this->refmap.get_phys_x(order);
926 double* y = this->refmap.get_phys_y(order);
929 if (this->num_components == 1)
936 mat = this->refmap.get_const_inv_ref_map();
937 if (!this->refmap.is_jacobian_const()) { mat = this->refmap.get_inv_ref_map(order); mstep = 1; }
939 for (i = 0, m = mat; i < np; i++, m += mstep)
941 double jac = (*m)[0][0] * (*m)[1][1] - (*m)[1][0] * (*m)[0][1];
942 Scalar val, dx = 0.0, dy = 0.0;
945 this->values[0][1][i] = ((*m)[1][1] * dx - (*m)[0][1] * dy) / jac * (
static_cast<ExactSolutionVector<Scalar>*
>(
this))->exact_multiplicator;
946 this->values[0][2][i] = (-(*m)[1][0] * dx + (*m)[0][0] * dy) / jac * (
static_cast<ExactSolutionVector<Scalar>*
>(
this))->exact_multiplicator;
951 for (i = 0; i < np; i++)
953 Scalar val, dx = 0.0, dy = 0.0;
963 for (i = 0; i < np; i++)
965 Scalar2<Scalar> dx(0.0, 0.0), dy(0.0, 0.0);
967 for (j = 0; j < 2; j++)
978 throw Hermes::Exceptions::Exception(
"Cannot obtain values -- uninitialized solution. The solution was either "
979 "not calculated yet or you used the assignment operator which destroys "
980 "the solution on its right-hand side.");
999 xmlsolution.space().set(spaceTypeToString(this->get_space_type()));
1002 for (
unsigned int coeffs_i = 0; coeffs_i < this->num_coeffs; coeffs_i++)
1006 for (
unsigned int elems_i = 0; elems_i < this->num_elems; elems_i++)
1010 for (
unsigned int component_i = 0; component_i < this->num_components; component_i++)
1013 xmlsolution.component().back().component_number() = component_i;
1014 for (
unsigned int elems_i = 0; elems_i < this->num_elems; elems_i++)
1015 xmlsolution.component().back().elem_coeffs().push_back(
XMLSolution::elem_coeffs(elems_i, elem_coeffs[component_i][elems_i]));
1020 std::ofstream out(filename);
1027 throw Hermes::Exceptions::SolutionSaveFailureException(e.what());
1032 void Solution<std::complex<double> >::save(
const char* filename)
const
1044 xmlsolution.space().set(spaceTypeToString(this->get_space_type()));
1047 for (
unsigned int coeffs_i = 0; coeffs_i < this->num_coeffs; coeffs_i++)
1050 xmlsolution.mono_coeffs().back().im() = mono_coeffs[coeffs_i].imag();
1054 for (
unsigned int elems_i = 0; elems_i < this->num_elems; elems_i++)
1058 for (
unsigned int component_i = 0; component_i < this->num_components; component_i++)
1061 xmlsolution.component().back().component_number() = component_i;
1062 for (
unsigned int elems_i = 0; elems_i < this->num_elems; elems_i++)
1063 xmlsolution.component().back().elem_coeffs().push_back(
XMLSolution::elem_coeffs(elems_i, elem_coeffs[component_i][elems_i]));
1068 std::ofstream out(filename);
1075 throw Hermes::Exceptions::SolutionSaveFailureException(e.what());
1081 void Solution<double>::save_bson(
const char* filename)
const
1091 bson_append_string(&bw,
"space", spaceTypeToString(this->get_space_type()));
1094 bson_append_bool(&bw,
"exact",
false);
1097 bson_append_bool(&bw,
"complex",
false);
1100 bson_append_int(&bw,
"coeffs_count", this->num_coeffs);
1101 bson_append_int(&bw,
"orders_count", this->num_elems);
1102 bson_append_int(&bw,
"components_count", this->num_components);
1105 bson_append_start_array(&bw,
"coeffs");
1106 for (
unsigned int coeffs_i = 0; coeffs_i < this->num_coeffs; coeffs_i++)
1107 bson_append_double(&bw,
"c", mono_coeffs[coeffs_i]);
1108 bson_append_finish_array(&bw);
1111 bson_append_start_array(&bw,
"orders");
1112 for (
unsigned int elems_i = 0; elems_i < this->num_elems; elems_i++)
1113 bson_append_int(&bw,
"o", elem_orders[elems_i]);
1114 bson_append_finish_array(&bw);
1117 bson_append_start_array(&bw,
"components");
1118 for (
unsigned int component_i = 0; component_i < this->num_components; component_i++)
1120 bson_append_start_array(&bw,
"component");
1121 for (
unsigned int elems_i = 0; elems_i < this->num_elems; elems_i++)
1122 bson_append_int(&bw,
"c", elem_coeffs[component_i][elems_i]);
1123 bson_append_finish_array(&bw);
1125 bson_append_finish_array(&bw);
1132 fpw = fopen(filename,
"wb");
1133 const char *dataw = (
const char *)bson_data(&bw);
1134 fwrite(dataw, bson_size(&bw), 1, fpw);
1141 void Solution<std::complex<double> >::save_bson(
const char* filename)
const
1151 bson_append_string(&bw,
"space", spaceTypeToString(this->get_space_type()));
1154 bson_append_bool(&bw,
"exact",
false);
1157 bson_append_bool(&bw,
"complex",
true);
1160 bson_append_int(&bw,
"coeffs_count", this->num_coeffs);
1161 bson_append_int(&bw,
"orders_count", this->num_elems);
1162 bson_append_int(&bw,
"components_count", this->num_components);
1165 bson_append_start_array(&bw,
"coeffs-real");
1166 for (
unsigned int coeffs_i = 0; coeffs_i < this->num_coeffs; coeffs_i++)
1167 bson_append_double(&bw,
"c", mono_coeffs[coeffs_i].real());
1168 bson_append_finish_array(&bw);
1170 bson_append_start_array(&bw,
"coeffs-imag");
1171 for (
unsigned int coeffs_i = 0; coeffs_i < this->num_coeffs; coeffs_i++)
1172 bson_append_double(&bw,
"c", mono_coeffs[coeffs_i].imag());
1173 bson_append_finish_array(&bw);
1176 bson_append_start_array(&bw,
"orders");
1177 for (
unsigned int elems_i = 0; elems_i < this->num_elems; elems_i++)
1178 bson_append_int(&bw,
"o", elem_orders[elems_i]);
1179 bson_append_finish_array(&bw);
1182 bson_append_start_array(&bw,
"components");
1183 for (
unsigned int component_i = 0; component_i < this->num_components; component_i++)
1185 bson_append_start_array(&bw,
"component");
1186 for (
unsigned int elems_i = 0; elems_i < this->num_elems; elems_i++)
1187 bson_append_int(&bw,
"c", elem_coeffs[component_i][elems_i]);
1188 bson_append_finish_array(&bw);
1190 bson_append_finish_array(&bw);
1197 fpw = fopen(filename,
"wb");
1198 const char *dataw = (
const char *)bson_data(&bw);
1199 fwrite(dataw, bson_size(&bw), 1, fpw);
1208 double x_real,
double y_real,
double x_complex,
double y_complex)
1210 switch (number_of_components)
1215 double* coeff_vec = malloc_with_check<double>(space->get_num_dofs());
1216 MeshFunctionSharedPtr<double> sln(
new ConstantSolution<double>(this->mesh, x_real));
1217 OGProjection<double>::project_global(space, sln, coeff_vec);
1218 this->set_coeff_vector(space, coeff_vec,
true, 0);
1219 sln_type = HERMES_SLN;
1222 throw Hermes::Exceptions::SolutionLoadFailureException(
"Mismatched real - complex exact solutions.");
1227 double* coeff_vec = malloc_with_check<double>(space->get_num_dofs());
1228 MeshFunctionSharedPtr<double> sln(
new ConstantSolutionVector<double>(this->mesh, x_real, y_real));
1229 OGProjection<double>::project_global(space, sln, coeff_vec);
1230 this->set_coeff_vector(space, coeff_vec,
true, 0);
1231 this->sln_type = HERMES_SLN;
1234 throw Hermes::Exceptions::SolutionLoadFailureException(
"Mismatched real - complex exact solutions.");
1240 void Solution<std::complex<double> >::load_exact_solution(
int number_of_components, SpaceSharedPtr<std::complex<double> > space,
bool complexness,
1241 double x_real,
double y_real,
double x_complex,
double y_complex)
1243 switch (number_of_components)
1248 std::complex<double>* coeff_vec = malloc_with_check<std::complex<double> >(space->get_num_dofs());
1249 MeshFunctionSharedPtr<std::complex<double> > sln(
new ConstantSolution<std::complex<double> >(this->mesh, std::complex<double>(x_real, x_complex)));
1250 OGProjection<std::complex<double> >::project_global(space, sln, coeff_vec);
1251 this->set_coeff_vector(space, coeff_vec,
true, 0);
1252 sln_type = HERMES_SLN;
1255 throw Hermes::Exceptions::SolutionLoadFailureException(
"Mismatched real - complex exact solutions.");
1258 if (complexness == 1)
1260 std::complex<double>* coeff_vec = malloc_with_check<std::complex<double> >(space->get_num_dofs());
1261 MeshFunctionSharedPtr<std::complex<double> > sln(
new ConstantSolutionVector<std::complex<double> >(this->mesh, std::complex<double>(x_real, x_complex), std::complex<double>(y_real, y_complex)));
1262 OGProjection<std::complex<double> >::project_global(space, sln, coeff_vec);
1263 this->set_coeff_vector(space, coeff_vec,
true, 0);
1264 sln_type = HERMES_SLN;
1267 throw Hermes::Exceptions::SolutionLoadFailureException(
"Mismatched real - complex exact solutions.");
1276 this->mesh = space->get_mesh();
1277 this->space_type = space->get_type();
1282 if (!this->validate)
1283 parsing_flags = xml_schema::flags::dont_validate;
1285 std::auto_ptr<XMLSolution::solution> parsed_xml_solution(
XMLSolution::solution_(filename, parsing_flags));
1286 sln_type = parsed_xml_solution->exact() == 0 ? HERMES_SLN : HERMES_EXACT;
1288 if (parsed_xml_solution->ncmp() != space->get_shapeset()->get_num_components())
1289 throw Exceptions::Exception(
"Mismatched space / saved solution.");
1291 if (sln_type == HERMES_EXACT)
1292 this->load_exact_solution(parsed_xml_solution->ncmp(), space, parsed_xml_solution->exactC(), parsed_xml_solution->exactCXR().get(), parsed_xml_solution->exactCYR().get(), parsed_xml_solution->exactCXC().get(), parsed_xml_solution->exactCYC().get());
1295 this->check_space_type_compliance(parsed_xml_solution->space().get().c_str());
1297 this->num_coeffs = parsed_xml_solution->nc();
1298 this->num_elems = parsed_xml_solution->nel();
1299 this->num_components = parsed_xml_solution->ncmp();
1301 this->mono_coeffs = malloc_with_check<Solution<double>,
double>(num_coeffs,
this);
1302 memset(this->mono_coeffs, 0, this->num_coeffs*
sizeof(
double));
1304 for (
unsigned int component_i = 0; component_i < num_components; component_i++)
1305 elem_coeffs[component_i] = malloc_with_check<Solution<double>,
int>(num_elems,
this);
1307 this->elem_orders = malloc_with_check<Solution<double>,
int>(num_elems,
this);
1309 for (
unsigned int coeffs_i = 0; coeffs_i < num_coeffs; coeffs_i++)
1310 this->mono_coeffs[parsed_xml_solution->mono_coeffs().at(coeffs_i).id()] = parsed_xml_solution->mono_coeffs().at(coeffs_i).re();
1312 for (
unsigned int elems_i = 0; elems_i < num_elems; elems_i++)
1313 this->elem_orders[parsed_xml_solution->elem_orders().at(elems_i).id()] = parsed_xml_solution->elem_orders().at(elems_i).ord();
1315 for (
unsigned int component_i = 0; component_i < this->num_components; component_i++)
1316 for (
unsigned int elems_i = 0; elems_i < num_elems; elems_i++)
1317 this->elem_coeffs[component_i][parsed_xml_solution->component().at(component_i).elem_coeffs().at(elems_i).id()] = parsed_xml_solution->component().at(component_i).elem_coeffs().at(elems_i).c();
1323 throw Hermes::Exceptions::SolutionLoadFailureException(e.what());
1328 void Solution<std::complex<double> >::load(
const char* filename, SpaceSharedPtr<std::complex<double> > space)
1331 sln_type = HERMES_SLN;
1332 this->mesh = space->get_mesh();
1333 this->space_type = space->get_type();
1338 if (!this->validate)
1339 parsing_flags = xml_schema::flags::dont_validate;
1341 std::auto_ptr<XMLSolution::solution> parsed_xml_solution(
XMLSolution::solution_(filename, parsing_flags));
1342 sln_type = parsed_xml_solution->exact() == 0 ? HERMES_SLN : HERMES_EXACT;
1344 if (parsed_xml_solution->ncmp() != space->get_shapeset()->get_num_components())
1345 throw Exceptions::Exception(
"Mismatched space / saved solution.");
1347 if (sln_type == HERMES_EXACT)
1348 this->load_exact_solution(parsed_xml_solution->ncmp(), space, parsed_xml_solution->exactC(), parsed_xml_solution->exactCXR().get(), parsed_xml_solution->exactCYR().get(), parsed_xml_solution->exactCXC().get(), parsed_xml_solution->exactCYC().get());
1351 this->check_space_type_compliance(parsed_xml_solution->space().get().c_str());
1354 if (!this->validate)
1355 parsing_flags = xml_schema::flags::dont_validate;
1357 std::auto_ptr<XMLSolution::solution> parsed_xml_solution(
XMLSolution::solution_(filename, parsing_flags));
1359 this->num_coeffs = parsed_xml_solution->nc();
1360 this->num_elems = parsed_xml_solution->nel();
1361 this->num_components = parsed_xml_solution->ncmp();
1363 this->mono_coeffs = malloc_with_check<Solution<std::complex<double> >, std::complex<double> >(num_coeffs,
this);
1364 memset(this->mono_coeffs, 0, this->num_coeffs*
sizeof(std::complex<double>));
1366 for (
unsigned int component_i = 0; component_i < num_components; component_i++)
1367 elem_coeffs[component_i] = malloc_with_check<Solution<std::complex<double> >,
int>(num_elems,
this);
1369 this->elem_orders = malloc_with_check<Solution<std::complex<double> >,
int>(num_elems,
this);
1371 for (
unsigned int coeffs_i = 0; coeffs_i < num_coeffs; coeffs_i++)
1372 this->mono_coeffs[parsed_xml_solution->mono_coeffs().at(coeffs_i).id()] = std::complex<double>(parsed_xml_solution->mono_coeffs().at(coeffs_i).re(), parsed_xml_solution->mono_coeffs().at(coeffs_i).im().get());
1374 for (
unsigned int elems_i = 0; elems_i < num_elems; elems_i++)
1375 this->elem_orders[parsed_xml_solution->elem_orders().at(elems_i).id()] = parsed_xml_solution->elem_orders().at(elems_i).ord();
1377 for (
unsigned int component_i = 0; component_i < this->num_components; component_i++)
1378 for (
unsigned int elems_i = 0; elems_i < num_elems; elems_i++)
1379 this->elem_coeffs[component_i][parsed_xml_solution->component().at(component_i).elem_coeffs().at(elems_i).id()] = parsed_xml_solution->component().at(component_i).elem_coeffs().at(elems_i).c();
1386 throw Hermes::Exceptions::SolutionLoadFailureException(e.what());
1392 void Solution<double>::load_bson(
const char* filename, SpaceSharedPtr<double> space)
1395 this->mesh = space->get_mesh();
1396 this->space_type = space->get_type();
1399 fpr = fopen(filename,
"rb");
1402 fseek(fpr, 0, SEEK_END);
1403 int size = ftell(fpr);
1407 char *datar = malloc_with_check<char>(size);
1408 fread(datar, size, 1, fpr);
1412 bson_init_finished_data(&br, datar, 0);
1418 bson_iterator it_exact;
1419 bson_find(&it_exact, &br,
"exact");
1420 sln_type = bson_iterator_bool(&it_exact) ? HERMES_EXACT : HERMES_SLN;
1422 bson_iterator it_complex;
1423 bson_find(&it_complex, &br,
"complex");
1424 bool is_complex = bson_iterator_bool(&it_complex);
1426 bson_iterator it_components;
1427 bson_find(&it_components, &br,
"components_count");
1428 if (bson_iterator_int(&it_components) != space->get_shapeset()->get_num_components())
1429 throw Exceptions::Exception(
"Mismatched space / saved solution.");
1431 this->num_components = bson_iterator_int(&it_components);
1433 if (sln_type == HERMES_EXACT)
1435 std::vector<double> values;
1437 bson_find(&it, &br,
"values");
1438 bson_iterator_subobject_init(&it, &sub, 0);
1439 bson_iterator_init(&it, &sub);
1440 while (bson_iterator_next(&it))
1441 values.push_back(bson_iterator_double(&it));
1442 this->load_exact_solution(this->num_components, space, is_complex, values[0], values[1], values[2], values[3]);
1447 bson_iterator it_sp;
1448 bson_find(&it_sp, &br,
"space");
1449 const char *sp = bson_iterator_string(&it_sp);
1451 this->check_space_type_compliance(sp);
1453 bson_iterator it_coeffs, it_orders;
1454 bson_find(&it_coeffs, &br,
"coeffs_count");
1455 bson_find(&it_orders, &br,
"orders_count");
1457 this->num_coeffs = bson_iterator_int(&it_coeffs);
1458 this->num_elems = bson_iterator_int(&it_orders);
1460 this->mono_coeffs = malloc_with_check<double>(num_coeffs);
1462 for (
unsigned int component_i = 0; component_i < num_components; component_i++)
1463 this->elem_coeffs[component_i] = malloc_with_check<int>(num_elems);
1465 this->elem_orders = malloc_with_check<int>(num_elems);
1468 bson_find(&it_coeffs, &br,
"coeffs");
1469 bson_iterator_subobject_init(&it_coeffs, &sub, 0);
1470 bson_iterator_init(&it, &sub);
1471 int index_coeff = 0;
1472 while (bson_iterator_next(&it))
1473 this->mono_coeffs[index_coeff++] = bson_iterator_double(&it);
1476 bson_find(&it_orders, &br,
"orders");
1477 bson_iterator_subobject_init(&it_orders, &sub, 0);
1478 bson_iterator_init(&it, &sub);
1479 int index_order = 0;
1480 while (bson_iterator_next(&it))
1481 this->elem_orders[index_order++] = bson_iterator_int(&it);
1484 bson_find(&it_components, &br,
"components");
1485 bson_iterator_subobject_init(&it_components, &sub, 0);
1486 bson_iterator_init(&it, &sub);
1488 while (bson_iterator_next(&it))
1491 bson_iterator_subobject_init(&it, &sub_coeffs, 0);
1492 bson_iterator it_coeffs;
1493 bson_iterator_init(&it_coeffs, &sub_coeffs);
1495 int index_coeff = 0;
1496 while (bson_iterator_next(&it_coeffs))
1497 this->elem_coeffs[index_comp][index_coeff++] = bson_iterator_int(&it_coeffs);
1504 free_with_check(datar);
1510 void Solution<std::complex<double> >::load_bson(
const char* filename, SpaceSharedPtr<std::complex<double> > space)
1513 this->mesh = space->get_mesh();
1514 this->space_type = space->get_type();
1517 fpr = fopen(filename,
"rb");
1520 fseek(fpr, 0, SEEK_END);
1521 int size = ftell(fpr);
1525 char *datar = malloc_with_check<char>(size);
1526 fread(datar, size, 1, fpr);
1530 bson_init_finished_data(&br, datar, 0);
1536 bson_iterator it_exact;
1537 bson_find(&it_exact, &br,
"exact");
1538 sln_type = bson_iterator_bool(&it_exact) ? HERMES_EXACT : HERMES_SLN;
1540 bson_iterator it_complex;
1541 bson_find(&it_complex, &br,
"complex");
1542 bool is_complex = bson_iterator_bool(&it_complex);
1544 bson_iterator it_components;
1545 bson_find(&it_components, &br,
"components_count");
1546 if (bson_iterator_int(&it_components) != space->get_shapeset()->get_num_components())
1547 throw Exceptions::Exception(
"Mismatched space / saved solution.");
1549 this->num_components = bson_iterator_int(&it_components);
1551 if (sln_type == HERMES_EXACT)
1553 std::vector<double> values;
1555 bson_find(&it, &br,
"values");
1556 bson_iterator_subobject_init(&it, &sub, 0);
1557 bson_iterator_init(&it, &sub);
1558 while (bson_iterator_next(&it))
1559 values.push_back(bson_iterator_double(&it));
1560 this->load_exact_solution(this->num_components, space, is_complex, values[0], values[1], values[2], values[3]);
1565 bson_iterator it_sp;
1566 bson_find(&it_sp, &br,
"space");
1567 const char *sp = bson_iterator_string(&it_sp);
1569 this->check_space_type_compliance(sp);
1571 bson_iterator it_coeffs, it_coeffs_real, it_coeffs_imag, it_orders;
1572 bson_find(&it_coeffs, &br,
"coeffs_count");
1573 bson_find(&it_orders, &br,
"orders_count");
1575 this->num_coeffs = bson_iterator_int(&it_coeffs);
1576 this->num_elems = bson_iterator_int(&it_orders);
1578 this->mono_coeffs = malloc_with_check<std::complex<double> >(num_coeffs);
1580 for (
unsigned int component_i = 0; component_i < num_components; component_i++)
1581 this->elem_coeffs[component_i] = malloc_with_check<int>(num_elems);
1583 this->elem_orders = malloc_with_check<int>(num_elems);
1586 std::vector<double> real_coeffs, imag_coeffs;
1587 bson_find(&it_coeffs_real, &br,
"coeffs-real");
1588 bson_iterator_subobject_init(&it_coeffs_real, &sub, 0);
1589 bson_iterator_init(&it, &sub);
1590 while (bson_iterator_next(&it))
1591 real_coeffs.push_back(bson_iterator_double(&it));
1593 bson_find(&it_coeffs_imag, &br,
"coeffs-imag");
1594 bson_iterator_subobject_init(&it_coeffs_imag, &sub, 0);
1595 bson_iterator_init(&it, &sub);
1596 while (bson_iterator_next(&it))
1597 imag_coeffs.push_back(bson_iterator_double(&it));
1599 for (
unsigned short i = 0; i < imag_coeffs.size(); i++)
1600 this->mono_coeffs[i] = std::complex<double>(real_coeffs[i], imag_coeffs[i]);
1603 bson_find(&it_orders, &br,
"orders");
1604 bson_iterator_subobject_init(&it_orders, &sub, 0);
1605 bson_iterator_init(&it, &sub);
1606 int index_order = 0;
1607 while (bson_iterator_next(&it))
1608 this->elem_orders[index_order++] = bson_iterator_int(&it);
1611 bson_find(&it_components, &br,
"components");
1612 bson_iterator_subobject_init(&it_components, &sub, 0);
1613 bson_iterator_init(&it, &sub);
1615 while (bson_iterator_next(&it))
1618 bson_iterator_subobject_init(&it, &sub_coeffs, 0);
1619 bson_iterator it_coeffs;
1620 bson_iterator_init(&it_coeffs, &sub_coeffs);
1622 int index_coeff = 0;
1623 while (bson_iterator_next(&it_coeffs))
1624 this->elem_coeffs[index_comp][index_coeff++] = bson_iterator_int(&it_coeffs);
1631 free_with_check(datar);
1637 template<
typename Scalar>
1642 okay = (this->sln_type == HERMES_EXACT || this->get_space_type() != HERMES_INVALID_SPACE) && okay;
1644 if (sln_type == HERMES_UNDEF)
1647 throw Exceptions::Exception(
"Uninitialized space type.");
1653 template<
typename Scalar>
1656 if (!strcmp(space_type_to_check,
"h1"))
1657 if (this->space_type != HERMES_H1_SPACE)
1658 throw Exceptions::Exception(
"Space types not compliant in Solution::load().");
1660 if (!strcmp(space_type_to_check,
"l2"))
1661 if (this->space_type != HERMES_L2_SPACE)
1662 throw Exceptions::Exception(
"Space types not compliant in Solution::load().");
1664 if (!strcmp(space_type_to_check,
"hcurl"))
1665 if (this->space_type != HERMES_HCURL_SPACE)
1666 throw Exceptions::Exception(
"Space types not compliant in Solution::load().");
1668 if (!strcmp(space_type_to_check,
"hdiv"))
1669 if (this->space_type != HERMES_HDIV_SPACE)
1670 throw Exceptions::Exception(
"Space types not compliant in Solution::load().");
1672 if (!strcmp(space_type_to_check,
"l2-markerwise"))
1673 if (this->space_type != HERMES_L2_MARKERWISE_CONST_SPACE)
1674 throw Exceptions::Exception(
"Space types not compliant in Solution::load().");
1677 template<
typename Scalar>
1680 Helpers::check_for_null(e);
1681 set_active_element(e);
1683 int o = elem_orders[e->
id];
1684 Scalar* mono = dxdy_coeffs[component][item];
1685 Scalar result = 0.0;
1687 for (
int i = 0; i <= o; i++)
1689 Scalar row = mono[k++];
1690 for (
int j = 0; j < (this->mode ? o : i); j++)
1691 row = row * xi1 + mono[k++];
1692 result = result * xi2 + row;
1695 this->invalidate_values();
1699 template<
typename Scalar>
1702 Helpers::check_for_null(e);
1704 if (this->sln_type != HERMES_SLN)
1705 throw Exceptions::Exception(
"Solution::get_ref_value_transformed only works for solutions wrt. FE space, project if you want to use the method for exact solutions.");
1707 set_active_element(e);
1709 if (this->num_components == 1)
1712 return get_ref_value(e, xi1, xi2, a, b);
1713 if (b == 1 || b == 2)
1717 this->refmap.inv_ref_map_at_point(xi1, xi2, xx, yy, m);
1718 Scalar dx = get_ref_value(e, xi1, xi2, a, 1);
1719 Scalar dy = get_ref_value(e, xi1, xi2, a, 2);
1721 if (b == 1)
return m[0][0] * dx + m[0][1] * dy;
1723 if (b == 2)
return m[1][0] * dx + m[1][1] * dy;
1725 #ifdef H2D_USE_SECOND_DERIVATIVES
1732 this->refmap.inv_ref_map_at_point(xi1, xi2, xx, yy, mat);
1734 Scalar vx = get_ref_value(e, xi1, xi2, a, 1);
1735 Scalar vy = get_ref_value(e, xi1, xi2, a, 2);
1736 Scalar vxx = get_ref_value(e, xi1, xi2, a, 3);
1737 Scalar vyy = get_ref_value(e, xi1, xi2, a, 4);
1738 Scalar vxy = get_ref_value(e, xi1, xi2, a, 5);
1739 this->refmap.second_ref_map_at_point(xi1, xi2, xx, yy, mat2);
1742 return sqr(mat[0][0])*vxx + 2 * mat[0][1] * mat[0][0] * vxy + sqr(mat[0][1])*vyy + mat2[0][0] * vx + mat2[0][1] * vy;
1745 return sqr(mat[1][0])*vxx + 2 * mat[1][1] * mat[1][0] * vxy + sqr(mat[1][1])*vyy + mat2[2][0] * vx + mat2[2][1] * vy;
1748 return mat[0][0] * mat[1][0] * vxx + (mat[0][0] * mat[1][1] + mat[1][0] * mat[0][1])*vxy + mat[0][1] * mat[1][1] * vyy + mat2[1][0] * vx + mat2[1][1] * vy;
1751 throw Exceptions::Exception(
"Hermes not built with second derivatives support. Consult the macro H2D_USE_SECOND_DERIVATIVES.");
1760 this->refmap.inv_ref_map_at_point(xi1, xi2, xx, yy, m);
1761 Scalar vx = get_ref_value(e, xi1, xi2, 0, 0);
1762 Scalar vy = get_ref_value(e, xi1, xi2, 1, 0);
1764 if (a == 0)
return m[0][0] * vx + m[0][1] * vy;
1766 if (a == 1)
return m[1][0] * vx + m[1][1] * vy;
1769 throw Hermes::Exceptions::Exception(
"Getting derivatives of the vector solution: Not implemented yet.");
1772 throw Hermes::Exceptions::Exception(
"Internal error: reached end of non-void function");
1776 template<
typename Scalar>
1779 set_active_element(e);
1781 double x_ref, y_ref;
1782 double x_dummy, y_dummy;
1784 this->get_refmap()->untransform(e, x, y, x_ref, y_ref);
1786 Scalar** toReturn = malloc_with_check<Solution<Scalar>, Scalar*>(2,
this);
1788 this->refmap.inv_ref_map_at_point(x_ref, y_ref, x_dummy, y_dummy, mat);
1789 if (this->num_components == 1)
1791 toReturn[0] = malloc_with_check<Solution<Scalar>, Scalar>(6,
this);
1793 int o = elem_orders[e->
id];
1795 Scalar result[H2D_NUM_FUNCTION_VALUES];
1796 for (
int item = 0; item < H2D_NUM_FUNCTION_VALUES; item++)
1798 Scalar* mono = dxdy_coeffs[0][item];
1799 Scalar result_local = 0.0;
1801 for (
int i = 0; i <= o; i++)
1803 Scalar row = mono[k++];
1804 for (
int j = 0; j < (this->mode ? o : i); j++)
1805 row = row * x_ref + mono[k++];
1806 result[item] = result_local * y_ref + row;
1810 toReturn[0][0] = result[0];
1811 toReturn[0][1] = mat[0][0] * result[1] + mat[0][1] * result[2];
1812 toReturn[0][2] = mat[1][0] * result[1] + mat[1][1] * result[2];
1813 #ifdef H2D_USE_SECOND_DERIVATIVES
1815 this->refmap.second_ref_map_at_point(x_ref, y_ref, x_dummy, y_dummy, mat2);
1817 toReturn[0][3] = sqr(mat[0][0])*result[3] + 2 * mat[0][1] * mat[0][0] * result[5] + sqr(mat[0][1])*result[4] + mat2[0][0] * result[1] + mat2[0][1] * result[2];
1818 toReturn[0][4] = sqr(mat[1][0])*result[3] + 2 * mat[1][1] * mat[1][0] * result[5] + sqr(mat[1][1])*result[4] + mat2[2][0] * result[1] + mat2[2][1] * result[2];
1819 toReturn[0][5] = mat[0][0] * mat[1][0] * result[3] + (mat[0][0] * mat[1][1] + mat[1][0] * mat[0][1])*result[5] + mat[0][1] * mat[1][1] * result[4] + mat2[1][0] * result[1] + mat2[1][1] * result[2];
1824 toReturn[0] = malloc_with_check<Solution<Scalar>, Scalar>(1,
this);
1826 Scalar vx = get_ref_value(e, x_ref, y_ref, 0, 0);
1827 Scalar vy = get_ref_value(e, x_ref, y_ref, 1, 0);
1828 toReturn[0][0] = mat[0][0] * vx + mat[0][1] * vy;
1829 toReturn[1][0] = mat[1][0] * vx + mat[1][1] * vy;
1832 this->invalidate_values();
1836 template<
typename Scalar>
1843 if (sln_type == HERMES_EXACT)
1845 if (this->num_components == 1)
1847 Scalar val, dx = 0.0, dy = 0.0;
1855 Scalar2<Scalar> dx(0.0, 0.0), dy(0.0, 0.0);
1860 #ifdef H2D_USE_SECOND_DERIVATIVES
1861 this->warn(
"Cannot obtain second derivatives of an exact solution.");
1865 else if (sln_type == HERMES_UNDEF)
1867 throw Hermes::Exceptions::Exception(
"Cannot obtain values -- uninitialized solution. The solution was either "
1868 "not calculated yet or you used the assignment operator which destroys "
1869 "the solution on its right-hand side.");
1875 e = RefMap::element_on_physical_coordinates(use_MeshHashGrid, this->mesh, x, y, &xi1, &xi2);
1877 RefMap::untransform(e, x, y, xi1, xi2);
1881 if (this->num_components == 1)
1883 toReturn->val[0] = get_ref_value(e, xi1, xi2, 0, 0);
1887 this->refmap.inv_ref_map_at_point(xi1, xi2, xx, yy, m);
1888 Scalar dx = get_ref_value(e, xi1, xi2, 0, 1);
1889 Scalar dy = get_ref_value(e, xi1, xi2, 0, 2);
1890 toReturn->dx[0] = m[0][0] * dx + m[0][1] * dy;
1891 toReturn->dy[0] = m[1][0] * dx + m[1][1] * dy;
1893 #ifdef H2D_USE_SECOND_DERIVATIVES
1894 toReturn->laplace = malloc_with_check(1,
this);
1898 this->refmap.inv_ref_map_at_point(xi1, xi2, xx, yy, mat);
1899 this->refmap.second_ref_map_at_point(xi1, xi2, xx, yy, mat2);
1901 Scalar vxx = get_ref_value(e, xi1, xi2, 0, 3);
1902 Scalar vyy = get_ref_value(e, xi1, xi2, 0, 4);
1903 Scalar vxy = get_ref_value(e, xi1, xi2, 0, 5);
1905 Scalar dxx = sqr(mat[0][0])*vxx + 2 * mat[0][1] * mat[0][0] * vxy + sqr(mat[0][1])*vyy + mat2[0][0] * dx + mat2[0][1] * dy;
1907 Scalar dyy = sqr(mat[1][0])*vxx + 2 * mat[1][1] * mat[1][0] * vxy + sqr(mat[1][1])*vyy + mat2[2][0] * dx + mat2[2][1] * dy;
1908 toReturn->laplace[0] = dxx + dyy;
1915 this->refmap.inv_ref_map_at_point(xi1, xi2, xx, yy, m);
1916 Scalar vx = get_ref_value(e, xi1, xi2, 0, 0);
1917 Scalar vy = get_ref_value(e, xi1, xi2, 1, 0);
1918 toReturn->val0[0] = m[0][0] * vx + m[0][1] * vy;
1919 toReturn->val1[0] = m[1][0] * vx + m[1][1] * vy;
1920 Hermes::Mixins::Loggable::Static::warn(
"Derivatives of vector functions not implemented yet.");
1925 this->warn(
"Point (%g, %g) does not lie in any element.", x, y);
virtual void copy(const MeshFunction< Scalar > *sln)
Copy from sln to this instance.
::xsd::cxx::tree::flags flags
Parsing and serialization flags.
Stores one element of a mesh.
Caches precalculated shape function values.
virtual void set_active_element(Element *e)
virtual void free()
Frees all precalculated tables.
Class corresponding to the mono_coeffs schema type.
Scalar * mono_coeffs
Monomial coefficient array.
void load_exact_solution(int number_of_components, SpaceSharedPtr< double > space, bool complexness, double x_real, double y_real, double x_complex, double y_complex)
Special internal method for loading exact solutions.
void set_dirichlet_lift(SpaceSharedPtr< Scalar > space)
Sets solution equal to Dirichlet lift only, solution vector = 0.
Class corresponding to the component schema type.
Represents a function defined on a mesh.
int * elem_coeffs[H2D_MAX_SOLUTION_COMPONENTS]
array of pointers into mono_coeffs
::xsd::cxx::tree::exception< char > exception
Root of the C++/Tree exception hierarchy.
Used to pass the instances of Space around.
::std::auto_ptr< ::XMLSolution::solution > solution_(const ::std::string &uri,::xml_schema::flags f=0, const ::xml_schema::properties &p=::xml_schema::properties())
Parse a URI or a local file.
Class corresponding to the elem_orders schema type.
virtual void precalculate(unsigned short order, unsigned short mask)
precalculates the current function at the current integration points.
Class corresponding to the solution schema type.
virtual MeshFunction< Scalar > * clone() const
virtual void set_active_element(Element *e)
Internal.
const int H2D_FN_DEFAULT
default precalculation mask
static void vector_to_solutions(const Scalar *solution_vector, std::vector< SpaceSharedPtr< Scalar > > spaces, std::vector< MeshFunctionSharedPtr< Scalar > > solutions, std::vector< bool > add_dir_lift=std::vector< bool >(), std::vector< int > start_indices=std::vector< int >())
Passes solution components calculated from solution vector as Solutions.
virtual void set_coeff_vector(SpaceSharedPtr< Scalar > space, const Vector< Scalar > *vec, bool add_dir_lift, int start_index)
Converts a coefficient vector into a Solution.
#define H2D_GET_H_ORDER(encoded_order)
Macros for combining quad horizontal and vertical encoded_orders.
::xsd::cxx::xml::dom::namespace_infomap< char > namespace_infomap
Namespace serialization information map.
virtual void save(const char *filename) const
Represents an exact solution of a PDE.
void get_center(double &x, double &y)
Returns the center of gravity.
virtual void add(MeshFunctionSharedPtr< Scalar > &other_mesh_function, SpaceSharedPtr< Scalar > target_space)
void enable_transform(bool enable=true)
const int H2D_FN_VAL
Both components are usually requested together...
Generated from solution_h2d_xml.xsd.
virtual void init()
Internal.
unsigned char num_components
Number of vector components.
virtual void precalculate(unsigned short order, unsigned short mask)
precalculates the current function at the current integration points.
void load(const char *filename, SpaceSharedPtr< double > space)
virtual void multiply(Scalar coef)
Multiplies the function represented by this class by the given coefficient.
Class corresponding to the elem_coeffs schema type.
Represents the solution of a PDE.
static void project_global(SpaceSharedPtr< Scalar > space, MatrixFormVol< Scalar > *custom_projection_jacobian, VectorFormVol< Scalar > *custom_projection_residual, Scalar *target_vec)
This method allows to specify your own OG-projection form.