16 #include "exact_solution.h"
20 #include "ogprojection.h"
30 static double3* cheb_tab_tri[11];
31 static double3* cheb_tab_quad[11];
32 static int cheb_np_tri[11];
33 static int cheb_np_quad[11];
35 static double3** cheb_tab[2] = { cheb_tab_tri, cheb_tab_quad };
36 static int* cheb_np[2] = { cheb_np_tri, cheb_np_quad };
38 static class Quad2DCheb :
public Quad2D
44 max_order[0] = max_order[1] = 10;
45 num_tables[0] = num_tables[1] = 11;
49 tables[0][0] = tables[1][0] = NULL;
50 np[0][0] = np[1][0] = 0;
54 for (
int mode_i = 0; mode_i <= 1; mode_i++)
56 for (k = 0; k <= 10; k++)
58 np[mode_i][k] = n = mode_i ? sqr(k + 1) : (k + 1)*(k + 2)/2;
59 tables[mode_i][k] = pt =
new double3[n];
61 for (i = k, m = 0; i >= 0; i--)
62 for (j = k; j >= (mode_i ? 0 : k-i); j--, m++) {
63 pt[m][0] = k ? cos(j * M_PI / k) : 1.0;
64 pt[m][1] = k ? cos(i * M_PI / k) : 1.0;
73 for (
int mode_i = 0; mode_i <= 1; mode_i++)
74 for (
int k = 1; k <= 10; k++)
75 delete [] tables[mode_i][k];
78 virtual void dummy_fn() {}
81 template<
typename Scalar>
82 void Solution<Scalar>::set_static_verbose_output(
bool verbose)
84 Solution<Scalar>::static_verbose_output = verbose;
87 template<
typename Scalar>
88 bool Solution<Scalar>::static_verbose_output =
false;
91 void Solution<double>::init()
93 memset(tables, 0,
sizeof(tables));
94 memset(elems, 0,
sizeof(elems));
95 memset(oldest, 0,
sizeof(oldest));
97 sln_type = HERMES_UNDEF;
98 this->num_components = 0;
101 for(
int i = 0; i < 4; i++)
102 for(
int j = 0; j < 4; j++)
103 tables[i][j] =
new std::map<uint64_t, LightArray<
struct Function<double>::Node*>*>;
106 elem_coeffs[0] = elem_coeffs[1] = NULL;
109 num_coeffs = num_elems = 0;
112 this->set_quad_2d(&g_quad_2d_std);
116 void Solution<std::complex<double> >::init()
118 memset(tables, 0,
sizeof(tables));
119 memset(elems, 0,
sizeof(elems));
120 memset(oldest, 0,
sizeof(oldest));
122 sln_type = HERMES_UNDEF;
123 this->num_components = 0;
126 for(
int i = 0; i < 4; i++)
127 for(
int j = 0; j < 4; j++)
128 tables[i][j] =
new std::map<uint64_t, LightArray<
struct Function<std::complex<double> >::Node*>*>;
131 elem_coeffs[0] = elem_coeffs[1] = NULL;
134 num_coeffs = num_elems = 0;
137 this->set_quad_2d(&g_quad_2d_std);
141 Solution<double>::Solution()
142 : MeshFunction<double>()
144 space_type = HERMES_INVALID_SPACE;
149 Solution<std::complex<double> >::Solution()
150 : MeshFunction<std::complex<double> >()
152 space_type = HERMES_INVALID_SPACE;
157 Solution<double>::Solution(
const Mesh *mesh) : MeshFunction<double>(mesh)
159 space_type = HERMES_INVALID_SPACE;
165 Solution<std::complex<double> >::Solution(
const Mesh *mesh) : MeshFunction<std::complex<double> >(mesh)
167 space_type = HERMES_INVALID_SPACE;
173 Solution<double>::Solution(Space<double>* s, Vector<double>* coeff_vec) : MeshFunction<double>(s->get_mesh())
175 space_type = s->get_type();
177 this->mesh = s->get_mesh();
178 Solution<double>::vector_to_solution(coeff_vec, s,
this);
182 Solution<std::complex<double> >::Solution(Space<std::complex<double> >* s, Vector<std::complex<double> >* coeff_vec) : MeshFunction<std::complex<double> >(s->get_mesh())
184 space_type = s->get_type();
186 this->mesh = s->get_mesh();
187 Solution<std::complex<double> >::vector_to_solution(coeff_vec, s,
this);
191 Solution<double>::Solution(Space<double>* s,
double* coeff_vec) : MeshFunction<double>(s->get_mesh())
193 space_type = s->get_type();
195 this->mesh = s->get_mesh();
196 Solution<double>::vector_to_solution(coeff_vec, s,
this);
200 Solution<std::complex<double> >::Solution(Space<std::complex<double> >* s, std::complex<double> * coeff_vec) : MeshFunction<std::complex<double> >(s->get_mesh())
202 space_type = s->get_type();
204 this->mesh = s->get_mesh();
205 Solution<std::complex<double> >::vector_to_solution(coeff_vec, s,
this);
208 template<
typename Scalar>
209 void Solution<Scalar>::assign(Solution<Scalar>* sln)
211 if(sln->sln_type == HERMES_UNDEF)
throw Hermes::Exceptions::Exception(
"Solution being assigned is uninitialized.");
212 if(sln->sln_type != HERMES_SLN) { copy(sln);
return; }
216 this->mesh = sln->mesh;
218 space_type = sln->get_space_type();
220 mono_coeffs = sln->mono_coeffs; sln->mono_coeffs = NULL;
221 elem_coeffs[0] = sln->elem_coeffs[0]; sln->elem_coeffs[0] = NULL;
222 elem_coeffs[1] = sln->elem_coeffs[1]; sln->elem_coeffs[1] = NULL;
223 elem_orders = sln->elem_orders; sln->elem_orders = NULL;
224 dxdy_buffer = sln->dxdy_buffer; sln->dxdy_buffer = NULL;
225 num_coeffs = sln->num_coeffs; sln->num_coeffs = 0;
226 num_elems = sln->num_elems; sln->num_elems = 0;
228 sln_type = sln->sln_type;
229 this->num_components = sln->num_components;
231 memset(sln->tables, 0,
sizeof(sln->tables));
234 template<
typename Scalar>
235 void Solution<Scalar>::copy(
const Solution<Scalar>* sln)
237 if(sln->sln_type == HERMES_UNDEF)
throw Hermes::Exceptions::Exception(
"Solution being copied is uninitialized.");
240 this->mesh = sln->mesh;
242 sln_type = sln->sln_type;
243 space_type = sln->get_space_type();
244 this->num_components = sln->num_components;
245 num_dofs = sln->num_dofs;
247 if(sln->sln_type == HERMES_SLN)
249 num_coeffs = sln->num_coeffs;
250 num_elems = sln->num_elems;
252 mono_coeffs =
new Scalar[num_coeffs];
253 memcpy(mono_coeffs, sln->mono_coeffs,
sizeof(Scalar) * num_coeffs);
255 for (
int l = 0; l < this->num_components; l++)
257 elem_coeffs[l] =
new int[num_elems];
258 memcpy(elem_coeffs[l], sln->elem_coeffs[l],
sizeof(
int) * num_elems);
261 elem_orders =
new int[num_elems];
262 memcpy(elem_orders, sln->elem_orders,
sizeof(
int) * num_elems);
267 throw Hermes::Exceptions::Exception(
"Undefined or exact solutions cannot be copied into an instance of Solution already coming from computation.");
269 this->element = NULL;
272 template<
typename Scalar>
273 MeshFunction<Scalar>* Solution<Scalar>::clone()
const
275 Solution<Scalar>* sln =
new Solution<Scalar>();
280 template<
typename Scalar>
281 void Solution<Scalar>::free_tables()
283 for (
int i = 0; i < 4; i++)
284 for (
int j = 0; j < 4; j++)
285 if(tables[i][j] != NULL)
287 for(
typename std::map<uint64_t, LightArray<
struct Function<Scalar>::Node*>*>::iterator it = tables[i][j]->begin(); it != tables[i][j]->end(); it++)
289 for(
unsigned int l = 0; l < it->second->get_size(); l++)
290 if(it->second->present(l))
291 ::free(it->second->get(l));
294 tables[i][j]->clear();
304 if(mono_coeffs != NULL) {
delete [] mono_coeffs; mono_coeffs = NULL; }
305 if(elem_orders != NULL) {
delete [] elem_orders; elem_orders = NULL; }
306 if(dxdy_buffer != NULL) {
delete [] dxdy_buffer; dxdy_buffer = NULL; }
308 for (
int i = 0; i < this->num_components; i++)
309 if(elem_coeffs[i] != NULL)
310 {
delete [] elem_coeffs[i]; elem_coeffs[i] = NULL; }
320 if(mono_coeffs != NULL) {
delete [] mono_coeffs; mono_coeffs = NULL; }
321 if(elem_orders != NULL) {
delete [] elem_orders; elem_orders = NULL; }
322 if(dxdy_buffer != NULL) {
delete [] dxdy_buffer; dxdy_buffer = NULL; }
324 for (
int i = 0; i < this->num_components; i++)
325 if(elem_coeffs[i] != NULL)
326 {
delete [] elem_coeffs[i]; elem_coeffs[i] = NULL; }
337 space_type = HERMES_INVALID_SPACE;
341 Solution<std::complex<double> >::~Solution()
344 space_type = HERMES_INVALID_SPACE;
347 static struct mono_lu_init
357 memset(mat, 0,
sizeof(mat));
362 for (
int m = 0; m <= 1; m++)
363 for (
int i = 0; i <= 10; i++)
364 if(mat[m][i] != NULL) {
366 delete [] perm[m][i];
372 template<
typename Scalar>
373 double** Solution<Scalar>::calc_mono_matrix(
int o,
int*& perm)
375 int i, j, k, l, m, row;
377 int n = this->mode ? sqr(o + 1) : (o + 1)*(o + 2)/2;
380 double** mat = new_matrix<double>(n, n);
381 for (k = o, row = 0; k >= 0; k--)
383 y = o ? cos(k * M_PI / o) : 1.0;
384 for (l = o; l >= (this->mode ? 0 : o-k); l--, row++)
386 x = o ? cos(l * M_PI / o) : 1.0;
389 for (i = 0, yn = 1.0, m = n-1; i <= o; i++, yn *= y)
390 for (j = (this->mode ? 0 : i), xn = 1.0; j <= o; j++, xn *= x, m--)
391 mat[row][m] = xn * yn;
397 ludcmp(mat, n, perm, &d);
401 template<
typename Scalar>
403 bool add_dir_lift,
int start_index)
406 if(space == NULL)
throw Exceptions::NullException(1);
407 if(vec == NULL)
throw Exceptions::NullException(2);
410 Scalar* coeffs =
new Scalar[vec->length()];
411 vec->extract(coeffs);
412 this->set_coeff_vector(space, coeffs, add_dir_lift, start_index);
416 template<
typename Scalar>
418 bool add_dir_lift,
int start_index)
421 if(space == NULL)
throw Exceptions::NullException(1);
424 Shapeset *shapeset = space->shapeset;
425 if(space->shapeset == NULL)
throw Exceptions::Exception(
"Space->shapeset == NULL in Solution<Scalar>::set_coeff_vector().");
427 if(pss == NULL)
throw Exceptions::Exception(
"PrecalcShapeset could not be allocated in Solution<Scalar>::set_coeff_vector().");
428 set_coeff_vector(space, pss, coeffs, add_dir_lift, start_index);
432 template<
typename Scalar>
433 void Solution<Scalar>::set_coeff_vector(
const Space<Scalar>* space, PrecalcShapeset* pss,
434 const Scalar* coeff_vec,
bool add_dir_lift,
int start_index)
437 if(Solution<Scalar>::static_verbose_output)
438 Hermes::Mixins::Loggable::Static::info(
"Solution: set_coeff_vector called.");
440 if(space == NULL)
throw Exceptions::NullException(1);
441 if(space->get_mesh() == NULL)
throw Exceptions::Exception(
"Mesh == NULL in Solution<Scalar>::set_coeff_vector().");
442 if(pss == NULL)
throw Exceptions::NullException(2);
443 if(coeff_vec == NULL)
throw Exceptions::NullException(3);
444 if(coeff_vec == NULL)
throw Exceptions::Exception(
"Coefficient vector == NULL in Solution<Scalar>::set_coeff_vector().");
445 if(!space->is_up_to_date())
446 throw Exceptions::Exception(
"Provided 'space' is not up to date.");
447 if(space->shapeset != pss->shapeset)
448 throw Exceptions::Exception(
"Provided 'space' and 'pss' must have the same shapesets.");
450 if(Solution<Scalar>::static_verbose_output)
451 Hermes::Mixins::Loggable::Static::info(
"Solution: set_coeff_vector - solution being freed.");
455 this->space_type = space->get_type();
457 this->num_components = pss->get_num_components();
458 sln_type = HERMES_SLN;
461 this->mesh = space->get_mesh();
464 num_elems = this->mesh->get_max_element_id();
465 if(elem_orders != NULL)
466 delete [] elem_orders;
467 elem_orders =
new int[num_elems];
468 memset(elem_orders, 0,
sizeof(
int) * num_elems);
469 for (
int l = 0; l < this->num_components; l++)
471 if(elem_coeffs[l] != NULL)
472 delete [] elem_coeffs[l];
473 elem_coeffs[l] =
new int[num_elems];
474 memset(elem_coeffs[l], 0,
sizeof(
int) * num_elems);
480 for_all_active_elements(e, this->mesh)
482 this->mode = e->get_mode();
483 o = space->get_element_order(e->id);
485 for (
unsigned int k = 0; k < e->get_nvert(); k++)
487 int eo = space->get_edge_order(e, k);
492 if((space->shapeset)->get_num_components() == 2) o++;
494 num_coeffs += this->mode ? sqr(o + 1) : (o + 1)*(o + 2)/2;
495 elem_orders[e->id] = o;
497 num_coeffs *= this->num_components;
498 if(mono_coeffs != NULL)
499 delete [] mono_coeffs;
500 mono_coeffs =
new Scalar[num_coeffs];
503 Quad2D* quad = &g_quad_2d_cheb;
504 pss->set_quad_2d(quad);
505 Scalar* mono = mono_coeffs;
506 for_all_active_elements(e, this->mesh)
508 this->mode = e->get_mode();
509 o = elem_orders[e->id];
510 int np = quad->get_num_points(o, e->get_mode());
513 space->get_element_assembly_list(e, &al);
514 pss->set_active_element(e);
516 for (
int l = 0; l < this->num_components; l++)
520 elem_coeffs[l][e->id] = (int) (mono - mono_coeffs);
521 memset(val, 0,
sizeof(Scalar)*np);
522 for (
unsigned int k = 0; k < al.cnt; k++)
524 pss->set_active_shape(al.idx[k]);
525 pss->set_quad_order(o, H2D_FN_VAL);
527 double dir_lift_coeff = add_dir_lift ? 1.0 : 0.0;
531 Scalar coef = al.coef[k] * (dof >= 0 ? coeff_vec[dof - space->first_dof + start_index] : dir_lift_coeff);
532 double* shape = pss->get_fn_values(l);
533 for (
int i = 0; i < np; i++)
534 val[i] += shape[i] * coef;
539 if(mono_lu.mat[this->mode][o] == NULL)
540 mono_lu.mat[this->mode][o] = calc_mono_matrix(o, mono_lu.perm[this->mode][o]);
541 lubksb(mono_lu.mat[this->mode][o], np, mono_lu.perm[this->mode][o], val);
545 if(this->mesh == NULL)
throw Hermes::Exceptions::Exception(
"mesh == NULL.\n");
547 this->element = NULL;
548 if(Solution<Scalar>::static_verbose_output)
549 Hermes::Mixins::Loggable::Static::info(
"Solution: set_coeff_vector - done.");
552 template<
typename Scalar>
555 Hermes::vector<bool> add_dir_lift, Hermes::vector<int> start_indices)
557 if(solution_vector == NULL)
throw Exceptions::NullException(1);
558 if(spaces.size() != solutions.size())
throw Exceptions::LengthException(2, 3, spaces.size(), solutions.size());
561 Hermes::vector<int> start_indices_new;
562 if(start_indices.empty())
565 for (
int i=0; i < spaces.size(); i++)
567 start_indices_new.push_back(counter);
568 counter += spaces[i]->get_num_dofs();
573 if(start_indices.size() != spaces.size())
throw Hermes::Exceptions::Exception(
"Mismatched start indices in vector_to_solutions().");
574 for (
int i=0; i < spaces.size(); i++)
576 start_indices_new.push_back(start_indices[i]);
580 for(
unsigned int i = 0; i < solutions.size(); i++)
585 Hermes::Mixins::Loggable::Static::info(
"Solution: %d-th solution", i);
587 Hermes::Mixins::Loggable::Static::info(
"Solution: %d-st solution", i);
589 Hermes::Mixins::Loggable::Static::info(
"Solution: %d-nd solution", i);
591 Hermes::Mixins::Loggable::Static::info(
"Solution: %d-rd solution", i);
593 Hermes::Mixins::Loggable::Static::info(
"Solution: %d-th solution", i);
595 if(add_dir_lift == Hermes::vector<bool>())
604 template<
typename Scalar>
609 if(solution_vector == NULL)
throw Exceptions::NullException(1);
610 if(space == NULL)
throw Exceptions::NullException(2);
611 if(solution == NULL)
throw Exceptions::NullException(3);
613 solution->
set_coeff_vector(space, solution_vector, add_dir_lift, start_index);
616 template<
typename Scalar>
617 void Solution<Scalar>::vector_to_solutions(
const Vector<Scalar>* solution_vector, Hermes::vector<
const Space<Scalar>*> spaces,
618 Hermes::vector<Solution<Scalar>*> solutions, Hermes::vector<bool> add_dir_lift, Hermes::vector<int> start_indices)
620 if(solution_vector == NULL)
throw Exceptions::NullException(1);
621 if(spaces.size() != solutions.size())
throw Exceptions::LengthException(2, 3, spaces.size(), solutions.size());
624 Hermes::vector<int> start_indices_new;
625 if(start_indices.empty())
628 for (
int i=0; i < spaces.size(); i++)
630 start_indices_new.push_back(counter);
631 counter += spaces[i]->get_num_dofs();
636 if(start_indices.size() != spaces.size())
throw Hermes::Exceptions::Exception(
"Mismatched start indices in vector_to_solutions().");
637 for (
int i=0; i < spaces.size(); i++)
639 start_indices_new.push_back(start_indices[i]);
643 for(
unsigned int i = 0; i < solutions.size(); i++)
645 if(Solution<Scalar>::static_verbose_output)
648 Hermes::Mixins::Loggable::Static::info(
"Solution: %d-th solution", i);
650 Hermes::Mixins::Loggable::Static::info(
"Solution: %d-st solution", i);
652 Hermes::Mixins::Loggable::Static::info(
"Solution: %d-nd solution", i);
654 Hermes::Mixins::Loggable::Static::info(
"Solution: %d-rd solution", i);
656 Hermes::Mixins::Loggable::Static::info(
"Solution: %d-th solution", i);
658 if(add_dir_lift == Hermes::vector<bool>())
659 Solution<Scalar>::vector_to_solution(solution_vector, spaces[i], solutions[i],
true, start_indices_new[i]);
661 Solution<Scalar>::vector_to_solution(solution_vector, spaces[i], solutions[i], add_dir_lift[i], start_indices_new[i]);
667 template<
typename Scalar>
668 void Solution<Scalar>::vector_to_solutions_common_dir_lift(
const Vector<Scalar>* solution_vector, Hermes::vector<
const Space<Scalar>*> spaces,
669 Hermes::vector<Solution<Scalar>*> solutions,
bool add_dir_lift)
671 if(solution_vector == NULL)
throw Exceptions::NullException(1);
672 if(spaces.size() != solutions.size())
throw Exceptions::LengthException(2, 3, spaces.size(), solutions.size());
675 Hermes::vector<int> start_indices_new;
677 for (
int i=0; i < spaces.size(); i++)
679 start_indices_new.push_back(counter);
680 counter += spaces[i]->get_num_dofs();
683 for(
unsigned int i = 0; i < solutions.size(); i++)
684 Solution<Scalar>::vector_to_solution(solution_vector, spaces[i], solutions[i], add_dir_lift, start_indices_new[i]);
689 template<
typename Scalar>
690 void Solution<Scalar>::vector_to_solutions_common_dir_lift(
const Scalar* solution_vector, Hermes::vector<
const Space<Scalar>*> spaces,
691 Hermes::vector<Solution<Scalar>*> solutions,
bool add_dir_lift)
693 if(solution_vector == NULL)
throw Exceptions::NullException(1);
694 if(spaces.size() != solutions.size())
throw Exceptions::LengthException(2, 3, spaces.size(), solutions.size());
697 Hermes::vector<int> start_indices_new;
699 for (
int i=0; i < spaces.size(); i++)
701 start_indices_new.push_back(counter);
702 counter += spaces[i]->get_num_dofs();
705 for(
unsigned int i = 0; i < solutions.size(); i++)
706 Solution<Scalar>::vector_to_solution(solution_vector, spaces[i], solutions[i], add_dir_lift, start_indices_new[i]);
711 template<
typename Scalar>
712 void Solution<Scalar>::vector_to_solution(
const Vector<Scalar>* solution_vector,
const Space<Scalar>* space,
713 Solution<Scalar>* solution,
bool add_dir_lift,
int start_index)
716 if(solution_vector == NULL)
throw Exceptions::NullException(1);
717 if(space == NULL)
throw Exceptions::NullException(2);
718 if(solution == NULL)
throw Exceptions::NullException(3);
720 solution->set_coeff_vector(space, solution_vector, add_dir_lift, start_index);
723 template<
typename Scalar>
724 void Solution<Scalar>::vector_to_solutions(
const Scalar* solution_vector, Hermes::vector<
const Space<Scalar>*> spaces,
725 Hermes::vector<Solution<Scalar>*> solutions, Hermes::vector<PrecalcShapeset *> pss,
726 Hermes::vector<bool> add_dir_lift, Hermes::vector<int> start_indices)
728 if(solution_vector==NULL)
throw Exceptions::NullException(1);
729 if(spaces.size() != solutions.size())
throw Exceptions::LengthException(2, 3, spaces.size(), solutions.size());
732 Hermes::vector<int> start_indices_new;
733 if(start_indices.empty())
736 for (
int i=0; i < spaces.size(); i++)
738 start_indices_new.push_back(counter);
739 counter += spaces[i]->get_num_dofs();
744 if(start_indices.size() != spaces.size())
throw Hermes::Exceptions::Exception(
"Mismatched start indices in vector_to_solutions().");
745 for (
int i=0; i < spaces.size(); i++)
747 start_indices_new.push_back(start_indices[i]);
751 for(
unsigned int i = 0; i < solutions.size(); i++)
753 if(Solution<Scalar>::static_verbose_output)
756 Hermes::Mixins::Loggable::Static::info(
"Solution: %d-th solution", i);
758 Hermes::Mixins::Loggable::Static::info(
"Solution: %d-st solution", i);
760 Hermes::Mixins::Loggable::Static::info(
"Solution: %d-nd solution", i);
762 Hermes::Mixins::Loggable::Static::info(
"Solution: %d-rd solution", i);
764 Hermes::Mixins::Loggable::Static::info(
"Solution: %d-th solution", i);
766 if(add_dir_lift == Hermes::vector<bool>())
767 Solution<Scalar>::vector_to_solution(solution_vector, spaces[i], solutions[i],
true, start_indices_new[i]);
769 Solution<Scalar>::vector_to_solution(solution_vector, spaces[i], solutions[i], add_dir_lift[i], start_indices_new[i]);
775 template<
typename Scalar>
776 void Solution<Scalar>::vector_to_solution(
const Scalar* solution_vector,
const Space<Scalar>* space, Solution<Scalar>* solution,
777 PrecalcShapeset* pss,
bool add_dir_lift,
int start_index)
779 if(solution_vector == NULL)
throw Exceptions::NullException(1);
780 if(space == NULL)
throw Exceptions::NullException(2);
781 if(solution == NULL)
throw Exceptions::NullException(3);
782 if(pss == NULL)
throw Exceptions::NullException(4);
784 solution->set_coeff_vector(space, pss, solution_vector, add_dir_lift, start_index);
787 template<
typename Scalar>
792 Scalar *temp =
new Scalar[ndof];
793 memset(temp, 0,
sizeof(Scalar)*ndof);
794 bool add_dir_lift =
true;
796 this->set_coeff_vector(space, pss, temp, add_dir_lift, start_index);
800 template<
typename Scalar>
803 if(transform != enable) free_tables();
807 template<
typename Scalar>
810 if(sln_type == HERMES_SLN)
812 for (
int i = 0; i < num_coeffs; i++)
813 mono_coeffs[i] *= coef;
815 else if(sln_type == HERMES_EXACT)
818 throw Hermes::Exceptions::Exception(
"Uninitialized solution.");
821 template<
typename Scalar>
822 static void make_dx_coeffs(
int mode,
int o, Scalar* mono, Scalar* result)
825 for (i = 0; i <= o; i++) {
828 for (j = 0; j < k; j++)
829 *result++= (Scalar) (k-j) * mono[j];
834 template<
typename Scalar>
835 static void make_dy_coeffs(
int mode,
int o, Scalar* mono, Scalar* result)
839 for (j = 0; j <= o; j++)
841 for (i = 0; i < o; i++)
842 for (j = 0; j <= o; j++)
843 *result++= (Scalar) (o-i) * (*mono++);
846 for (i = 0; i <= o; i++) {
848 for (j = 0; j < i; j++)
849 *result++= (Scalar) (o + 1-i) * (*mono++);
854 template<
typename Scalar>
855 void Solution<Scalar>::init_dxdy_buffer()
857 if(dxdy_buffer != NULL)
859 delete [] dxdy_buffer;
862 dxdy_buffer =
new Scalar[this->num_components * 5 * 121];
865 template<
typename Scalar>
868 if(e == this->element)
870 if(!e->
active)
throw Hermes::Exceptions::Exception(
"Cannot select inactive element. Wrong mesh?");
874 for (cur_elem = 0; cur_elem < 4; cur_elem++)
875 if(elems[this->cur_quad][cur_elem] == e)
881 if(tables[this->cur_quad][oldest[this->cur_quad]] != NULL)
883 for(
typename std::map<uint64_t, LightArray<
struct Function<Scalar>::Node*>*>::iterator it = tables[this->cur_quad][oldest[this->cur_quad]]->begin(); it != tables[this->cur_quad][oldest[this->cur_quad]]->end(); it++)
885 for(
unsigned int l = 0; l < it->second->get_size(); l++)
886 if(it->second->present(l))
887 ::free(it->second->get(l));
890 delete tables[this->cur_quad][oldest[this->cur_quad]];
891 tables[this->cur_quad][oldest[this->cur_quad]] = NULL;
892 elems[this->cur_quad][oldest[this->cur_quad]] = NULL;
895 tables[this->cur_quad][oldest[this->cur_quad]] =
new std::map<uint64_t, LightArray<struct Function<Scalar>::Node*>*>;
897 cur_elem = oldest[this->cur_quad];
898 if(++oldest[this->cur_quad] >= 4)
899 oldest[this->cur_quad] = 0;
901 elems[this->cur_quad][cur_elem] = e;
904 if(sln_type == HERMES_SLN)
906 int o = this->order = elem_orders[this->element->id];
907 int n = this->mode ? sqr(o + 1) : (o + 1)*(o + 2)/2;
909 for (
int i = 0, m = 0; i < this->num_components; i++)
911 Scalar* mono = mono_coeffs + elem_coeffs[i][e->
id];
912 dxdy_coeffs[i][0] = mono;
914 make_dx_coeffs(this->mode, o, mono, dxdy_coeffs[i][1] = dxdy_buffer + m); m += n;
915 make_dy_coeffs(this->mode, o, mono, dxdy_coeffs[i][2] = dxdy_buffer + m); m += n;
916 make_dx_coeffs(this->mode, o, dxdy_coeffs[i][1], dxdy_coeffs[i][3] = dxdy_buffer + m); m += n;
917 make_dy_coeffs(this->mode, o, dxdy_coeffs[i][2], dxdy_coeffs[i][4] = dxdy_buffer + m); m += n;
918 make_dx_coeffs(this->mode, o, dxdy_coeffs[i][2], dxdy_coeffs[i][5] = dxdy_buffer + m); m += n;
921 else if(sln_type == HERMES_EXACT)
923 this->order = Hermes::Hermes2D::g_max_quad;
926 throw Hermes::Exceptions::Exception(
"Uninitialized solution.");
928 this->sub_tables = tables[this->cur_quad][cur_elem];
930 this->update_nodes_ptr();
933 template<
typename Scalar>
934 static inline void set_vec_num(
int n, Scalar* y, Scalar num)
936 for (
int i = 0; i < n; i++)
940 template<
typename Scalar>
941 static inline void vec_x_vec_p_num(
int n, Scalar* y, Scalar* x, Scalar num)
943 for (
int i = 0; i < n; i++)
944 y[i] = y[i]*x[i] + num;
947 template<
typename Scalar>
948 static inline void vec_x_vec_p_vec(
int n, Scalar* y, Scalar* x, Scalar* z)
950 for (
int i = 0; i < n; i++)
951 y[i] = y[i]*x[i] + z[i];
954 static const int H2D_GRAD = H2D_FN_DX_0 | H2D_FN_DY_0;
955 static const int H2D_SECOND = H2D_FN_DXX_0 | H2D_FN_DXY_0 | H2D_FN_DYY_0;
956 static const int H2D_CURL = H2D_FN_DX | H2D_FN_DY;
958 template<
typename Scalar>
959 void Solution<Scalar>::transform_values(
int order,
struct Function<Scalar>::Node* node,
int newmask,
int oldmask,
int np)
962 double3x2 *mat2, *mm;
966 if(space_type == HERMES_H1_SPACE)
968 #ifdef H2D_USE_SECOND_DERIVATIVES
969 if(((newmask & H2D_SECOND) == H2D_SECOND && (oldmask & H2D_SECOND) != H2D_SECOND))
971 this->update_refmap();
972 mat = this->refmap->get_inv_ref_map(order);
973 mat2 = this->refmap->get_second_ref_map(order);
974 for (i = 0, m = mat, mm = mat2; i < np; i++, m++, mm++)
976 Scalar vx = node->values[0][1][i];
977 Scalar vy = node->values[0][2][i];
978 Scalar vxx = node->values[0][3][i];
979 Scalar vyy = node->values[0][4][i];
980 Scalar vxy = node->values[0][5][i];
982 node->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;
983 node->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;
984 node->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;
988 if((newmask & H2D_GRAD) == H2D_GRAD && (oldmask & H2D_GRAD) != H2D_GRAD)
990 this->update_refmap();
991 mat = this->refmap->get_const_inv_ref_map();
992 if(!this->refmap->is_jacobian_const()) { mat = this->refmap->get_inv_ref_map(order); mstep = 1; }
994 for (i = 0, m = mat; i < np; i++, m += mstep)
996 Scalar vx = node->values[0][1][i];
997 Scalar vy = node->values[0][2][i];
998 node->values[0][1][i] = (*m)[0][0]*vx + (*m)[0][1]*vy;
999 node->values[0][2][i] = (*m)[1][0]*vx + (*m)[1][1]*vy;
1005 else if(space_type == HERMES_HCURL_SPACE)
1007 bool trans_val =
false, trans_curl =
false;
1008 if((newmask & H2D_FN_VAL) == H2D_FN_VAL && (oldmask & H2D_FN_VAL) != H2D_FN_VAL) trans_val =
true;
1009 if((newmask & H2D_CURL) == H2D_CURL && (oldmask & H2D_CURL) != H2D_CURL) trans_curl =
true;
1011 if(trans_val || trans_curl)
1013 this->update_refmap();
1014 mat = this->refmap->get_const_inv_ref_map();
1015 if(!this->refmap->is_jacobian_const()) { mat = this->refmap->get_inv_ref_map(order); mstep = 1; }
1017 for (i = 0, m = mat; i < np; i++, m += mstep)
1021 Scalar vx = node->values[0][0][i];
1022 Scalar vy = node->values[1][0][i];
1023 node->values[0][0][i] = (*m)[0][0]*vx + (*m)[0][1]*vy;
1024 node->values[1][0][i] = (*m)[1][0]*vx + (*m)[1][1]*vy;
1028 Scalar e0x = node->values[0][1][i], e0y = node->values[0][2][i];
1029 Scalar e1x = node->values[1][1][i], e1y = node->values[1][2][i];
1030 node->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);
1031 node->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);
1038 else if(space_type == HERMES_HDIV_SPACE)
1040 if((newmask & H2D_FN_VAL) == H2D_FN_VAL && (oldmask & H2D_FN_VAL) != H2D_FN_VAL)
1042 this->update_refmap();
1043 mat = this->refmap->get_const_inv_ref_map();
1044 if(!this->refmap->is_jacobian_const()) { mat = this->refmap->get_inv_ref_map(order); mstep = 1; }
1046 for (i = 0, m = mat; i < np; i++, m += mstep)
1048 Scalar vx = node->values[0][0][i];
1049 Scalar vy = node->values[1][0][i];
1050 node->values[0][0][i] = (*m)[1][1]*vx - (*m)[1][0]*vy;
1051 node->values[1][0][i] = - (*m)[0][1]*vx + (*m)[0][0]*vy;
1057 template<
typename Scalar>
1062 Quad2D* quad = this->quads[this->cur_quad];
1063 int np = quad->get_num_points(order, this->mode);
1065 if(sln_type == HERMES_SLN)
1068 const int H2D_GRAD = H2D_FN_DX_0 | H2D_FN_DY_0;
1069 const int H2D_SECOND = H2D_FN_DXX_0 | H2D_FN_DXY_0 | H2D_FN_DYY_0;
1070 const int H2D_CURL = H2D_FN_DX | H2D_FN_DY;
1073 if(this->num_components == 1)
1075 if((mask & H2D_FN_DX_0) || (mask & H2D_FN_DY_0)) mask |= H2D_GRAD;
1076 if((mask & H2D_FN_DXX_0) || (mask & H2D_FN_DXY_0) || (mask & H2D_FN_DYY_0)) mask |= H2D_SECOND;
1078 else if(space_type == HERMES_HCURL_SPACE)
1079 {
if((mask & H2D_FN_VAL_0) || (mask & H2D_FN_VAL_1)) mask |= H2D_FN_VAL;
1080 if((mask & H2D_FN_DX_1) || (mask & H2D_FN_DY_0)) mask |= H2D_CURL; }
1082 {
if((mask & H2D_FN_VAL_0) || (mask & H2D_FN_VAL_1)) mask |= H2D_FN_VAL; }
1085 int oldmask = (this->cur_node != NULL) ? this->cur_node->mask : 0;
1086 int newmask = mask | oldmask;
1087 node = this->new_node(newmask, np);
1090 Scalar* x =
new Scalar[np];
1091 Scalar* y =
new Scalar[np];
1092 Scalar* tx =
new Scalar[np];
1093 double3* pt = quad->get_points(order, this->element->get_mode());
1094 for (i = 0; i < np; i++)
1096 x[i] = pt[i][0] * this->ctm->m[0] + this->ctm->t[0];
1097 y[i] = pt[i][1] * this->ctm->m[1] + this->ctm->t[1];
1101 int o = elem_orders[this->element->id];
1102 for (l = 0; l < this->num_components; l++)
1104 for (k = 0; k < 6; k++)
1106 if(newmask & this->idx2mask[k][l])
1108 Scalar* result = node->values[l][k];
1109 if(oldmask & this->idx2mask[k][l])
1112 memcpy(result, this->cur_node->values[l][k], np *
sizeof(Scalar));
1117 Scalar* mono = dxdy_coeffs[l][k];
1118 for (i = 0; i <= o; i++)
1120 set_vec_num(np, tx, *mono++);
1121 for (j = 1; j <= (this->mode ? o : i); j++)
1122 vec_x_vec_p_num(np, tx, x, *mono++);
1125 memcpy(result, tx,
sizeof(Scalar)*np);
1127 vec_x_vec_p_vec(np, result, y, tx);
1140 transform_values(order, node, newmask, oldmask, np);
1142 else if(sln_type == HERMES_EXACT)
1145 throw Hermes::Exceptions::Exception(
"Cannot obtain second derivatives of an exact solution.");
1148 this->update_refmap();
1149 double* x = this->refmap->get_phys_x(order);
1150 double* y = this->refmap->get_phys_y(order);
1153 if(this->num_components == 1)
1160 mat = this->refmap->get_const_inv_ref_map();
1161 if(!this->refmap->is_jacobian_const()) { mat = this->refmap->get_inv_ref_map(order); mstep = 1; }
1163 for (i = 0, m = mat; i < np; i++, m += mstep)
1165 double jac = (*m)[0][0] * (*m)[1][1] - (*m)[1][0] * (*m)[0][1];
1166 Scalar val, dx = 0.0, dy = 0.0;
1169 node->values[0][1][i] = ( (*m)[1][1]*dx - (*m)[0][1]*dy) / jac * (
static_cast<ExactSolutionVector<Scalar>*
>(
this))->exact_multiplicator;
1170 node->values[0][2][i] = (- (*m)[1][0]*dx + (*m)[0][0]*dy) / jac * (
static_cast<ExactSolutionVector<Scalar>*
>(
this))->exact_multiplicator;
1175 for (i = 0; i < np; i++)
1177 Scalar val, dx = 0.0, dy = 0.0;
1187 for (i = 0; i < np; i++)
1189 Scalar2<Scalar> dx (0.0, 0.0 ), dy ( 0.0, 0.0 );
1191 for (j = 0; j < 2; j++)
1202 throw Hermes::Exceptions::Exception(
"Cannot obtain values -- uninitialized solution. The solution was either "
1203 "not calculated yet or you used the assignment operator which destroys "
1204 "the solution on its right-hand side.");
1207 if(this->nodes->present(order))
1209 assert(this->nodes->get(order) == this->cur_node);
1210 ::free(this->nodes->get(order));
1212 this->nodes->add(node, order);
1213 this->cur_node = node;
1219 if(sln_type == HERMES_UNDEF)
1220 throw Exceptions::Exception(
"Cannot save -- uninitialized solution.");
1225 switch(this->get_space_type())
1227 case HERMES_H1_SPACE:
1228 xmlsolution.space().set(
"h1");
1230 case HERMES_HCURL_SPACE:
1231 xmlsolution.space().set(
"hcurl");
1233 case HERMES_HDIV_SPACE:
1234 xmlsolution.space().set(
"hdiv");
1236 case HERMES_L2_SPACE:
1237 xmlsolution.space().set(
"l2");
1241 for(
unsigned int coeffs_i = 0; coeffs_i < this->num_coeffs; coeffs_i++)
1244 for(
unsigned int elems_i = 0; elems_i < this->num_elems; elems_i++)
1247 for (
unsigned int component_i = 0; component_i < this->num_components; component_i++)
1250 xmlsolution.component().back().component_number() = component_i;
1251 for(
unsigned int elems_i = 0; elems_i < this->num_elems; elems_i++)
1252 xmlsolution.component().back().elem_coeffs().push_back(
XMLSolution::elem_coeffs(elems_i, elem_coeffs[component_i][elems_i]));
1255 std::string solution_schema_location(Hermes2DApi.get_text_param_value(xmlSchemasDirPath));
1256 solution_schema_location.append(
"/solution_h2d_xml.xsd");
1260 namespace_info_map.insert(std::pair<std::basic_string<char>,
xml_schema::namespace_info>(
"solution", namespace_info_solution));
1262 std::ofstream out(filename);
1271 throw Hermes::Exceptions::SolutionSaveFailureException(e.what());
1277 void Solution<std::complex<double> >::save(
const char* filename)
const
1279 if(sln_type == HERMES_UNDEF)
1280 throw Exceptions::Exception(
"Cannot save -- uninitialized solution.");
1286 switch(this->get_space_type())
1288 case HERMES_H1_SPACE:
1289 xmlsolution.space().set(
"h1");
1291 case HERMES_HCURL_SPACE:
1292 xmlsolution.space().set(
"hcurl");
1294 case HERMES_HDIV_SPACE:
1295 xmlsolution.space().set(
"hdiv");
1297 case HERMES_L2_SPACE:
1298 xmlsolution.space().set(
"l2");
1302 for(
unsigned int coeffs_i = 0; coeffs_i < this->num_coeffs; coeffs_i++)
1305 xmlsolution.mono_coeffs().back().im() = mono_coeffs[coeffs_i].imag();
1308 for(
unsigned int elems_i = 0; elems_i < this->num_elems; elems_i++)
1311 for (
unsigned int component_i = 0; component_i < this->num_components; component_i++)
1314 xmlsolution.component().back().component_number() = component_i;
1315 for(
unsigned int elems_i = 0; elems_i < this->num_elems; elems_i++)
1316 xmlsolution.component().back().elem_coeffs().push_back(
XMLSolution::elem_coeffs(elems_i, elem_coeffs[component_i][elems_i]));
1320 solution_schema_location.append(
"/solution_h2d_xml.xsd");
1324 namespace_info_map.insert(std::pair<std::basic_string<char>,
xml_schema::namespace_info>(
"solution", namespace_info_solution));
1326 std::ofstream out(filename);
1335 throw Hermes::Exceptions::SolutionSaveFailureException(e.what());
1341 void Solution<double>::load(
const char* filename, Space<double>* space)
1344 this->mesh = space->get_mesh();
1345 this->space_type = space->get_type();
1351 parsing_flags = xml_schema::flags::dont_validate;
1353 std::auto_ptr<XMLSolution::solution> parsed_xml_solution(
XMLSolution::solution_(filename, parsing_flags));
1354 sln_type = parsed_xml_solution->exact() == 0 ? HERMES_SLN : HERMES_EXACT;
1356 if(sln_type == HERMES_EXACT)
1358 switch(parsed_xml_solution->ncmp())
1361 if(parsed_xml_solution->exactC() == 0)
1363 double* coeff_vec =
new double[space->get_num_dofs()];
1364 ConstantSolution<double> sln(mesh, parsed_xml_solution->exactCXR().get());
1365 OGProjection<double> ogProj;
1366 ogProj.project_global(space, &sln, coeff_vec);
1367 this->set_coeff_vector(space, coeff_vec,
true, 0);
1368 sln_type = HERMES_SLN;
1371 throw Hermes::Exceptions::SolutionLoadFailureException(
"Mismatched real - complex exact solutions.");
1374 if(parsed_xml_solution->exactC() == 0)
1376 double* coeff_vec =
new double[space->get_num_dofs()];
1377 ConstantSolutionVector<double> sln(mesh, parsed_xml_solution->exactCXR().get(), parsed_xml_solution->exactCYR().get());
1378 OGProjection<double> ogProj;
1379 ogProj.project_global(space, &sln, coeff_vec);
1380 this->set_coeff_vector(space, coeff_vec,
true, 0);
1381 sln_type = HERMES_SLN;
1384 throw Hermes::Exceptions::SolutionLoadFailureException(
"Mismatched real - complex exact solutions.");
1390 if(!strcmp(parsed_xml_solution->space().get().c_str(),
"h1"))
1391 if(this->space_type != HERMES_H1_SPACE)
1392 throw Exceptions::Exception(
"Space types not compliant in Solution::load().");
1394 if(!strcmp(parsed_xml_solution->space().get().c_str(),
"l2"))
1395 if(this->space_type != HERMES_L2_SPACE)
1396 throw Exceptions::Exception(
"Space types not compliant in Solution::load().");
1398 if(!strcmp(parsed_xml_solution->space().get().c_str(),
"hcurl"))
1399 if(this->space_type != HERMES_HCURL_SPACE)
1400 throw Exceptions::Exception(
"Space types not compliant in Solution::load().");
1402 if(!strcmp(parsed_xml_solution->space().get().c_str(),
"hdiv"))
1403 if(this->space_type != HERMES_HDIV_SPACE)
1404 throw Exceptions::Exception(
"Space types not compliant in Solution::load().");
1406 this->num_coeffs = parsed_xml_solution->nc();
1407 this->num_elems = parsed_xml_solution->nel();
1408 this->num_components = parsed_xml_solution->ncmp();
1410 this->mono_coeffs =
new double[num_coeffs];
1411 memset(this->mono_coeffs, 0, this->num_coeffs*
sizeof(
double));
1413 for(
unsigned int component_i = 0; component_i < num_components; component_i++)
1414 elem_coeffs[component_i] =
new int[num_elems];
1416 this->elem_orders =
new int[num_elems];
1418 for (
unsigned int coeffs_i = 0; coeffs_i < num_coeffs; coeffs_i++)
1419 this->mono_coeffs[parsed_xml_solution->mono_coeffs().at(coeffs_i).id()] = parsed_xml_solution->mono_coeffs().at(coeffs_i).re();
1421 for (
unsigned int elems_i = 0; elems_i < num_elems; elems_i++)
1422 this->elem_orders[parsed_xml_solution->elem_orders().at(elems_i).id()] = parsed_xml_solution->elem_orders().at(elems_i).ord();
1424 for (
unsigned int component_i = 0; component_i < this->num_components; component_i++)
1425 for (
unsigned int elems_i = 0; elems_i < num_elems; elems_i++)
1426 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();
1433 throw Hermes::Exceptions::SolutionLoadFailureException(e.what());
1439 void Solution<std::complex<double> >::load(
const char* filename, Space<std::complex<double> >* space)
1442 sln_type = HERMES_SLN;
1443 this->mesh = space->get_mesh();
1444 this->space_type = space->get_type();
1450 parsing_flags = xml_schema::flags::dont_validate;
1452 std::auto_ptr<XMLSolution::solution> parsed_xml_solution(
XMLSolution::solution_(filename, parsing_flags));
1453 sln_type = parsed_xml_solution->exact() == 0 ? HERMES_SLN : HERMES_EXACT;
1455 if(sln_type == HERMES_EXACT)
1457 switch(parsed_xml_solution->ncmp())
1460 if(parsed_xml_solution->exactC() == 1)
1462 std::complex<double>* coeff_vec =
new std::complex<double>[space->get_num_dofs()];
1463 ConstantSolution<std::complex<double> > sln(mesh, std::complex<double>(parsed_xml_solution->exactCXR().get(), parsed_xml_solution->exactCXC().get()));
1464 OGProjection<std::complex<double> > ogProj;
1465 ogProj.project_global(space, &sln, coeff_vec);
1466 this->set_coeff_vector(space, coeff_vec,
true, 0);
1467 sln_type = HERMES_SLN;
1470 throw Hermes::Exceptions::SolutionLoadFailureException(
"Mismatched real - complex exact solutions.");
1473 if(parsed_xml_solution->exactC() == 1)
1475 std::complex<double>* coeff_vec =
new std::complex<double>[space->get_num_dofs()];
1476 ConstantSolutionVector<std::complex<double> > sln(mesh, std::complex<double>(parsed_xml_solution->exactCXR().get(), parsed_xml_solution->exactCXC().get()), std::complex<double>(parsed_xml_solution->exactCYR().get(), parsed_xml_solution->exactCYC().get()));
1477 OGProjection<std::complex<double> > ogProj;
1478 ogProj.project_global(space, &sln, coeff_vec);
1479 this->set_coeff_vector(space, coeff_vec,
true, 0);
1480 sln_type = HERMES_SLN;
1483 throw Hermes::Exceptions::SolutionLoadFailureException(
"Mismatched real - complex exact solutions.");
1489 if(!strcmp(parsed_xml_solution->space().get().c_str(),
"h1"))
1490 if(this->space_type != HERMES_H1_SPACE)
1491 throw Exceptions::Exception(
"Space types not compliant in Solution::load().");
1493 if(!strcmp(parsed_xml_solution->space().get().c_str(),
"l2"))
1494 if(this->space_type != HERMES_L2_SPACE)
1495 throw Exceptions::Exception(
"Space types not compliant in Solution::load().");
1497 if(!strcmp(parsed_xml_solution->space().get().c_str(),
"hcurl"))
1498 if(this->space_type != HERMES_HCURL_SPACE)
1499 throw Exceptions::Exception(
"Space types not compliant in Solution::load().");
1501 if(!strcmp(parsed_xml_solution->space().get().c_str(),
"hdiv"))
1502 if(this->space_type != HERMES_HDIV_SPACE)
1503 throw Exceptions::Exception(
"Space types not compliant in Solution::load().");
1507 parsing_flags = xml_schema::flags::dont_validate;
1509 std::auto_ptr<XMLSolution::solution> parsed_xml_solution(
XMLSolution::solution_(filename, parsing_flags));
1511 this->num_coeffs = parsed_xml_solution->nc();
1512 this->num_elems = parsed_xml_solution->nel();
1513 this->num_components = parsed_xml_solution->ncmp();
1515 this->mono_coeffs =
new std::complex<double>[num_coeffs];
1516 memset(this->mono_coeffs, 0, this->num_coeffs*
sizeof(std::complex<double>));
1518 for(
unsigned int component_i = 0; component_i < num_components; component_i++)
1519 elem_coeffs[component_i] =
new int[num_elems];
1521 this->elem_orders =
new int[num_elems];
1523 for (
unsigned int coeffs_i = 0; coeffs_i < num_coeffs; coeffs_i++)
1524 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());
1526 for (
unsigned int elems_i = 0; elems_i < num_elems; elems_i++)
1527 this->elem_orders[parsed_xml_solution->elem_orders().at(elems_i).id()] = parsed_xml_solution->elem_orders().at(elems_i).ord();
1529 for (
unsigned int component_i = 0; component_i < this->num_components; component_i++)
1530 for (
unsigned int elems_i = 0; elems_i < num_elems; elems_i++)
1531 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();
1538 throw Hermes::Exceptions::SolutionLoadFailureException(e.what());
1543 template<
typename Scalar>
1547 throw Exceptions::NullException(1);
1549 set_active_element(e);
1551 int o = elem_orders[e->
id];
1552 Scalar* mono = dxdy_coeffs[component][item];
1553 Scalar result = 0.0;
1555 for (
int i = 0; i <= o; i++)
1557 Scalar row = mono[k++];
1558 for (
int j = 0; j < (this->mode ? o : i); j++)
1559 row = row * xi1 + mono[k++];
1560 result = result * xi2 + row;
1565 template<
typename Scalar>
1568 if(e==NULL)
throw Exceptions::NullException(1);
1569 if(this->num_components == 1)
1572 return get_ref_value(e, xi1, xi2, a, b);
1573 if(b == 1 || b == 2)
1577 this->refmap->inv_ref_map_at_point(xi1, xi2, xx, yy, m);
1578 Scalar dx = get_ref_value(e_last = e, xi1, xi2, a, 1);
1579 Scalar dy = get_ref_value(e, xi1, xi2, a, 2);
1580 if(b == 1)
return m[0][0]*dx + m[0][1]*dy;
1581 if(b == 2)
return m[1][0]*dx + m[1][1]*dy;
1585 #ifdef H2D_USE_SECOND_DERIVATIVES
1590 this->refmap->inv_ref_map_at_point(xi1, xi2, xx, yy, mat);
1591 this->refmap->second_ref_map_at_point(xi1, xi2, xx, yy, mat2);
1593 Scalar vx = get_ref_value(e, xi1, xi2, a, 1);
1594 Scalar vy = get_ref_value(e, xi1, xi2, a, 2);
1595 Scalar vxx = get_ref_value(e, xi1, xi2, a, 3);
1596 Scalar vyy = get_ref_value(e, xi1, xi2, a, 4);
1597 Scalar vxy = get_ref_value(e, xi1, xi2, a, 5);
1599 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;
1601 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;
1603 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;
1613 this->refmap->inv_ref_map_at_point(xi1, xi2, xx, yy, m);
1614 Scalar vx = get_ref_value(e, xi1, xi2, 0, 0);
1615 Scalar vy = get_ref_value(e, xi1, xi2, 1, 0);
1616 if(a == 0)
return m[0][0]*vx + m[0][1]*vy;
1617 if(a == 1)
return m[1][0]*vx + m[1][1]*vy;
1620 throw Hermes::Exceptions::Exception(
"Getting derivatives of the vector solution: Not implemented yet.");
1622 throw Hermes::Exceptions::Exception(
"internal error: reached end of non-void function");
1626 template<
typename Scalar>
1633 if(sln_type == HERMES_EXACT)
1635 if(this->num_components == 1)
1637 Scalar val, dx = 0.0, dy = 0.0;
1639 toReturn->
val =
new Scalar[1];
1640 toReturn->dx =
new Scalar[1];
1641 toReturn->
dy =
new Scalar[1];
1648 Scalar2<Scalar> dx(0.0, 0.0), dy(0.0, 0.0);
1651 toReturn->val0 =
new Scalar[1];
1652 toReturn->dx0 =
new Scalar[1];
1653 toReturn->dy0 =
new Scalar[1];
1654 toReturn->
val1 =
new Scalar[1];
1655 toReturn->
dx1 =
new Scalar[1];
1656 toReturn->
dy1 =
new Scalar[1];
1664 #ifdef H2D_USE_SECOND_DERIVATIVES
1665 this->warn(
"Cannot obtain second derivatives of an exact solution.");
1668 else if(sln_type == HERMES_UNDEF)
1670 throw Hermes::Exceptions::Exception(
"Cannot obtain values -- uninitialized solution. The solution was either "
1671 "not calculated yet or you used the assignment operator which destroys "
1672 "the solution on its right-hand side.");
1676 Element* e = RefMap::element_on_physical_coordinates(this->mesh, x, y, &xi1, &xi2);
1679 if(this->num_components == 1)
1681 toReturn->
val =
new Scalar[1];
1682 toReturn->dx =
new Scalar[1];
1683 toReturn->
dy =
new Scalar[1];
1685 toReturn->
val[0] = get_ref_value(e, xi1, xi2, 0, 0);
1689 this->refmap->inv_ref_map_at_point(xi1, xi2, xx, yy, m);
1690 Scalar dx = get_ref_value(e, xi1, xi2, 0, 1);
1691 Scalar dy = get_ref_value(e, xi1, xi2, 0, 2);
1692 toReturn->dx[0] = m[0][0]*dx + m[0][1]*dy;
1693 toReturn->
dy[0] = m[1][0]*dx + m[1][1]*dy;
1695 #ifdef H2D_USE_SECOND_DERIVATIVES
1696 toReturn->
laplace =
new Scalar[1];
1700 this->refmap->inv_ref_map_at_point(xi1, xi2, xx, yy, mat);
1701 this->refmap->second_ref_map_at_point(xi1, xi2, xx, yy, mat2);
1703 Scalar vxx = get_ref_value(e, xi1, xi2, 0, 3);
1704 Scalar vyy = get_ref_value(e, xi1, xi2, 0, 4);
1705 Scalar vxy = get_ref_value(e, xi1, xi2, 0, 5);
1706 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;
1707 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;
1708 toReturn->
laplace[0] = dxx + dyy;
1713 toReturn->val0 =
new Scalar[1];
1714 toReturn->
val1 =
new Scalar[1];
1718 this->refmap->inv_ref_map_at_point(xi1, xi2, xx, yy, m);
1719 Scalar vx = get_ref_value(e, xi1, xi2, 0, 0);
1720 Scalar vy = get_ref_value(e, xi1, xi2, 1, 0);
1721 toReturn->val0[0] = m[0][0]*vx + m[0][1]*vy;
1722 toReturn->
val1[0] = m[1][0]*vx + m[1][1]*vy;
1723 Hermes::Mixins::Loggable::Static::warn(
"Derivatives of vector functions not implemented yet.");
1728 this->warn(
"Point (%g, %g) does not lie in any element.", x, y);