19 #include "exact_solution.h"
28 LinearizerCriterion::LinearizerCriterion(
bool adaptive) : adaptive(adaptive)
32 LinearizerCriterionAdaptive::LinearizerCriterionAdaptive(
double error_tolerance) : LinearizerCriterion(true)
34 this->error_tolerance = error_tolerance;
37 LinearizerCriterionFixed::LinearizerCriterionFixed(
int refinement_level) : LinearizerCriterion(false)
39 this->refinement_level = refinement_level;
42 template<
typename LinearizerDataDimensions>
44 states(nullptr), num_states(0), dmult(1.0), curvature_epsilon(1e-5), linearizerOutputType(linearizerOutputType), criterion(
LinearizerCriterionFixed(1))
55 for (
int i = 0; i < this->num_threads_used; i++)
59 pthread_mutexattr_t attr;
60 pthread_mutexattr_init(&attr);
61 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
62 pthread_mutex_init(&data_mutex, &attr);
63 pthread_mutexattr_destroy(&attr);
67 template<
typename LinearizerDataDimensions>
70 this->criterion = criterion;
73 template<
typename LinearizerDataDimensions>
76 this->curvature_epsilon = curvature_epsilon;
79 template<
typename LinearizerDataDimensions>
82 return this->curvature_epsilon;
85 template<
typename LinearizerDataDimensions>
91 this->user_xdisp =
true;
96 this->user_ydisp =
true;
102 template<
typename LinearizerDataDimensions>
105 for (
int k = 0; k < LinearizerDataDimensions::dimension; k++)
107 throw Exceptions::Exception(
"Linearizer: too few solutions, probably wrong template argument.");
110 template<
typename LinearizerDataDimensions>
114 this->check_data(sln);
117 for (
int k = 0; k < LinearizerDataDimensions::dimension; k++)
119 this->item[k] = item_[k];
120 this->component[k] = 0;
121 this->value_type[k] = 0;
129 while (!(item[k] & 1))
135 this->item[k] = item_[k];
140 for (
int k = 0; k < LinearizerDataDimensions::dimension; k++)
142 old_quad[k] = sln[k]->get_quad_2d();
143 meshes.push_back(sln[k]->get_mesh());
145 if (this->user_xdisp)
147 old_quad_x = xdisp->get_quad_2d();
148 meshes.push_back(xdisp->get_mesh());
150 if (this->user_ydisp)
152 old_quad_y = ydisp->get_quad_2d();
153 meshes.push_back(ydisp->get_mesh());
157 template<
typename LinearizerDataDimensions>
161 this->exceptionMessageCaughtInParallelBlock.clear();
167 this->init(sln, item_);
170 Traverse trav_master(ydisp ==
nullptr ? (xdisp ==
nullptr ? 1 : 2) : (xdisp ==
nullptr ? 2 : 3));
171 states = trav_master.get_states(this->meshes, this->num_states);
173 #pragma omp parallel shared(trav_master) num_threads(num_threads_used)
175 int thread_number = omp_get_thread_num();
176 int start = (this->num_states / num_threads_used) * thread_number;
177 int end = (this->num_states / num_threads_used) * (thread_number + 1);
178 if (thread_number == num_threads_used - 1)
179 end = this->num_states;
183 double max_value_for_adaptive_refinements = 0.;
185 this->threadLinearizerMultidimensional[thread_number]->init_processing(sln,
this);
187 for (
int state_i = start; state_i < end; state_i++)
188 max_value_for_adaptive_refinements = std::max(max_value_for_adaptive_refinements, this->threadLinearizerMultidimensional[thread_number]->get_max_value(states[state_i]));
190 this->threadLinearizerMultidimensional[thread_number]->max_value_approx = max_value_for_adaptive_refinements;
192 for (
int state_i = start; state_i < end; state_i++)
195 if (!this->exceptionMessageCaughtInParallelBlock.empty())
198 Traverse::State* current_state = states[state_i];
200 this->threadLinearizerMultidimensional[thread_number]->process_state(current_state);
202 this->threadLinearizerMultidimensional[thread_number]->deinit_processing();
204 catch (Hermes::Exceptions::Exception& e)
206 #pragma omp critical (exceptionMessageCaughtInParallelBlock)
207 this->exceptionMessageCaughtInParallelBlock = e.info();
211 #pragma omp critical (exceptionMessageCaughtInParallelBlock)
212 this->exceptionMessageCaughtInParallelBlock = e.what();
219 for (
int i = 0; i < this->num_states; i++)
222 free_with_check(this->states);
223 this->states =
nullptr;
224 this->num_states = 0;
230 if (!this->exceptionMessageCaughtInParallelBlock.empty())
231 throw Hermes::Exceptions::Exception(this->exceptionMessageCaughtInParallelBlock.c_str());
234 template<
typename LinearizerDataDimensions>
238 int items[LinearizerDataDimensions::dimension];
241 for (
int k = 1; k < LinearizerDataDimensions::dimension; k++)
247 this->process_solution(slns, items);
250 template<
typename LinearizerDataDimensions>
254 pthread_mutex_lock(&data_mutex);
258 template<
typename LinearizerDataDimensions>
262 pthread_mutex_unlock(&data_mutex);
266 template<
typename LinearizerDataDimensions>
270 if (this->exceptionMessageCaughtInParallelBlock.empty())
274 if (this->linearizerOutputType == FileExport)
276 int running_count = 0;
277 for (
int i = 0; i < this->num_threads_used; i++)
281 for (
int j = 0; j < this->threadLinearizerMultidimensional[i]->triangle_count; j++)
283 for (
int k = 0; k < 3; k++)
284 this->threadLinearizerMultidimensional[i]->triangle_indices[j][k] += running_count;
287 running_count += this->threadLinearizerMultidimensional[i]->vertex_count;
293 for (
int k = 0; k < LinearizerDataDimensions::dimension; k++)
294 sln[k]->set_quad_2d(old_quad[k]);
300 template<
typename LinearizerDataDimensions>
301 void LinearizerMultidimensional<LinearizerDataDimensions>::find_min_max()
304 this->min_val = 1e100;
305 this->max_val = -1e100;
306 for (Iterator<typename LinearizerDataDimensions::vertex_t> it = this->vertices_begin(); !it.end; ++it)
308 typename LinearizerDataDimensions::vertex_t& vertex = it.get();
310 double magnitude = 0.;
311 if (LinearizerDataDimensions::dimension == 1)
312 magnitude = vertex[2];
315 for (
int j = 0; j < LinearizerDataDimensions::dimension; j++)
316 magnitude += vertex[2 + j] * vertex[2 + j];
318 magnitude = std::sqrt(magnitude);
321 if (finite(magnitude) && magnitude < min_val)
323 if (finite(magnitude) && magnitude > max_val)
328 template<
typename LinearizerDataDimensions>
331 for (
int i = 0; i < this->num_threads_used; i++)
332 this->threadLinearizerMultidimensional[i]->free();
335 template<
typename LinearizerDataDimensions>
339 pthread_mutex_destroy(&data_mutex);
342 for (
int i = 0; i < this->num_threads_used; i++)
343 delete this->threadLinearizerMultidimensional[i];
344 free_with_check(this->threadLinearizerMultidimensional);
347 template<
typename LinearizerDataDimensions>
348 void LinearizerMultidimensional<LinearizerDataDimensions>::set_max_absolute_value(
double max_abs)
351 this->warn(
"Setting of maximum absolute value in LinearizerMultidimensional with a negative value");
354 this->max_val = max_abs;
359 template<
typename LinearizerDataDimensions>
360 double LinearizerMultidimensional<LinearizerDataDimensions>::get_min_value()
const
365 template<
typename LinearizerDataDimensions>
366 double LinearizerMultidimensional<LinearizerDataDimensions>::get_max_value()
const
371 template<
typename LinearizerDataDimensions>
375 if (this->linearizerOutputType != FileExport)
376 throw Exceptions::Exception(
"This LinearizerMultidimensional is not meant to be used for file export, create a new one with appropriate linearizerOutputType.");
378 process_solution(&slns[0], &items[0]);
380 FILE* f = fopen(filename,
"wb");
381 if (f ==
nullptr)
throw Hermes::Exceptions::Exception(
"Could not open %s for writing.", filename);
384 fprintf(f,
"# vtk DataFile Version 2.0\n");
386 fprintf(f,
"ASCII\n\n");
387 fprintf(f,
"DATASET UNSTRUCTURED_GRID\n");
390 fprintf(f,
"POINTS %d %s\n", this->get_vertex_count(),
"float");
393 typename LinearizerDataDimensions::vertex_t& vertex = it.get();
396 std::stringstream ss;
397 ss << vertex[0] <<
" " << vertex[1];
398 for (
int k = 0; k < LinearizerDataDimensions::dimension; k++)
399 ss <<
" " << vertex[2 + k];
400 fprintf(f,
"%s\n", ss.str().c_str());
403 fprintf(f,
"%g %g %g\n", vertex[0], vertex[1], 0.0);
408 fprintf(f,
"CELLS %d %d\n", this->get_triangle_count(), 4 * this->get_triangle_count());
412 fprintf(f,
"3 %d %d %d\n", triangle_indices[0], triangle_indices[1], triangle_indices[2]);
417 fprintf(f,
"CELL_TYPES %d\n", this->get_triangle_count());
418 for (
int i = 0; i < this->get_triangle_count(); i++)
426 fprintf(f,
"POINT_DATA %d\n", this->get_vertex_count());
427 fprintf(f,
"SCALARS %s %s %d\n", quantity_name,
"float", LinearizerDataDimensions::dimension);
428 fprintf(f,
"LOOKUP_TABLE %s\n",
"default");
431 typename LinearizerDataDimensions::vertex_t& vertex = it.get();
433 std::stringstream ssi;
434 for (
int k = 0; k < LinearizerDataDimensions::dimension; k++)
436 ssi << vertex[2 + k];
437 if (k < LinearizerDataDimensions::dimension - 1)
440 fprintf(f,
"%s\n", ssi.str().c_str());
446 template<
typename LinearizerDataDimensions>
449 std::vector<MeshFunctionSharedPtr<double> > slns;
450 std::vector<int> items;
452 items.push_back(item);
456 template<
typename LinearizerDataDimensions>
459 if (this->linearizerOutputType != FileExport)
460 throw Exceptions::Exception(
"This LinearizerMultidimensional is not meant to be used for file export, create a new one with appropriate linearizerOutputType.");
462 process_solution(&slns[0], &items[0]);
464 FILE* f = fopen(filename,
"wb");
465 if (f ==
nullptr)
throw Hermes::Exceptions::Exception(
"Could not open %s for writing.", filename);
468 fprintf(f,
"TITLE = \"%s created by Hermes.\"\n", filename);
469 std::stringstream ss;
470 ss <<
"VARIABLES = \"X\", \"Y\",";
471 for (
int k = 0; k < LinearizerDataDimensions::dimension; k++)
472 ss <<
" \"" << quantity_names[k] <<
"\"";
473 fprintf(f,
"%s\n", ss.str().c_str());
474 fprintf(f,
"ZONE N = %d, E = %d, DATAPACKING = POINT, ZONETYPE = FETRIANGLE\n", this->get_vertex_count(), this->get_triangle_count());
479 typename LinearizerDataDimensions::vertex_t& vertex = it.get();
481 std::stringstream ss;
482 ss << vertex[0] <<
" " << vertex[1];
483 for (
int k = 0; k < LinearizerDataDimensions::dimension; k++)
484 ss <<
" " << vertex[2 + k];
485 fprintf(f,
"%s\n", ss.str().c_str());
492 fprintf(f,
"%d %d %d\n", triangle_indices[0] + 1, triangle_indices[1] + 1, triangle_indices[2] + 1);
498 template<
typename LinearizerDataDimensions>
501 std::vector<MeshFunctionSharedPtr<double> > slns;
502 std::vector<int> items;
504 items.push_back(item);
505 std::vector<std::string> quantity_names;
506 quantity_names.push_back(quantity_name);
510 template<
typename LinearizerDataDimensions>
513 *max_x = *max_y = std::numeric_limits<double>::min();
514 *min_x = *min_y = std::numeric_limits<double>::max();
518 typename LinearizerDataDimensions::vertex_t& vertex = it.get();
519 if (vertex[0] > *max_x)
521 else if (vertex[0] < *min_x)
524 if (vertex[1] > *max_y)
526 else if (vertex[1] < *min_y)
531 template<
typename LinearizerDataDimensions>
537 template<
typename LinearizerDataDimensions>
541 if (this->current_thread_index >= this->current_thread_size - 1)
543 if (this->current_thread == this->thread_sizes.size() - 1)
547 this->current_thread_index = 0;
548 this->current_thread_size = this->thread_sizes[++this->current_thread];
549 this->check_zero_lengths();
553 this->current_thread_index++;
556 template<
typename LinearizerDataDimensions>
560 while (this->current_thread_size == 0)
562 if (this->current_thread_size == this->thread_sizes[this->thread_sizes.size() - 1])
567 this->current_thread_size = this->thread_sizes[++this->current_thread];
573 typename ScalarLinearizerDataDimensions<LINEARIZER_DATA_TYPE>::triangle_t& LinearizerMultidimensional<ScalarLinearizerDataDimensions<LINEARIZER_DATA_TYPE> >::Iterator<typename ScalarLinearizerDataDimensions<LINEARIZER_DATA_TYPE>::triangle_t>::get()
const
580 int& LinearizerMultidimensional<ScalarLinearizerDataDimensions<LINEARIZER_DATA_TYPE> >::Iterator<typename ScalarLinearizerDataDimensions<LINEARIZER_DATA_TYPE>::triangle_t>::get_marker()
const
582 return this->linearizer->threadLinearizerMultidimensional[this->current_thread]->triangle_markers[this->current_thread_index];
587 typename ScalarLinearizerDataDimensions<LINEARIZER_DATA_TYPE>::edge_t& LinearizerMultidimensional<ScalarLinearizerDataDimensions<LINEARIZER_DATA_TYPE> >::Iterator<typename ScalarLinearizerDataDimensions<LINEARIZER_DATA_TYPE>::edge_t>::get()
const
589 return this->linearizer->threadLinearizerMultidimensional[this->current_thread]->edges[this->current_thread_index];
594 int& LinearizerMultidimensional<ScalarLinearizerDataDimensions<LINEARIZER_DATA_TYPE> >::Iterator<typename ScalarLinearizerDataDimensions<LINEARIZER_DATA_TYPE>::edge_t>::get_marker()
const
596 return this->linearizer->threadLinearizerMultidimensional[this->current_thread]->edge_markers[this->current_thread_index];
601 typename ScalarLinearizerDataDimensions<LINEARIZER_DATA_TYPE>::vertex_t& LinearizerMultidimensional<ScalarLinearizerDataDimensions<LINEARIZER_DATA_TYPE> >::Iterator<typename ScalarLinearizerDataDimensions<LINEARIZER_DATA_TYPE>::vertex_t>::get()
const
603 return this->linearizer->threadLinearizerMultidimensional[this->current_thread]->vertices[this->current_thread_index];
608 triangle_indices_t& LinearizerMultidimensional<ScalarLinearizerDataDimensions<LINEARIZER_DATA_TYPE> >::Iterator<triangle_indices_t>::get()
const
610 return this->linearizer->threadLinearizerMultidimensional[this->current_thread]->triangle_indices[this->current_thread_index];
615 int& LinearizerMultidimensional<ScalarLinearizerDataDimensions<LINEARIZER_DATA_TYPE> >::Iterator<triangle_indices_t>::get_marker()
const
617 return this->linearizer->threadLinearizerMultidimensional[this->current_thread]->triangle_markers[this->current_thread_index];
622 typename VectorLinearizerDataDimensions<LINEARIZER_DATA_TYPE>::triangle_t& LinearizerMultidimensional<VectorLinearizerDataDimensions<LINEARIZER_DATA_TYPE> >::Iterator<typename VectorLinearizerDataDimensions<LINEARIZER_DATA_TYPE>::triangle_t>::get()
const
624 return this->linearizer->threadLinearizerMultidimensional[this->current_thread]->triangles[this->current_thread_index];
629 int& LinearizerMultidimensional<VectorLinearizerDataDimensions<LINEARIZER_DATA_TYPE> >::Iterator<typename VectorLinearizerDataDimensions<LINEARIZER_DATA_TYPE>::triangle_t>::get_marker()
const
631 return this->linearizer->threadLinearizerMultidimensional[this->current_thread]->triangle_markers[this->current_thread_index];
636 typename VectorLinearizerDataDimensions<LINEARIZER_DATA_TYPE>::edge_t& LinearizerMultidimensional<VectorLinearizerDataDimensions<LINEARIZER_DATA_TYPE> >::Iterator<typename VectorLinearizerDataDimensions<LINEARIZER_DATA_TYPE>::edge_t>::get()
const
638 return this->linearizer->threadLinearizerMultidimensional[this->current_thread]->edges[this->current_thread_index];
643 int& LinearizerMultidimensional<VectorLinearizerDataDimensions<LINEARIZER_DATA_TYPE> >::Iterator<typename VectorLinearizerDataDimensions<LINEARIZER_DATA_TYPE>::edge_t>::get_marker()
const
645 return this->linearizer->threadLinearizerMultidimensional[this->current_thread]->edge_markers[this->current_thread_index];
650 typename VectorLinearizerDataDimensions<LINEARIZER_DATA_TYPE>::vertex_t& LinearizerMultidimensional<VectorLinearizerDataDimensions<LINEARIZER_DATA_TYPE> >::Iterator<typename VectorLinearizerDataDimensions<LINEARIZER_DATA_TYPE>::vertex_t>::get()
const
652 return this->linearizer->threadLinearizerMultidimensional[this->current_thread]->vertices[this->current_thread_index];
657 triangle_indices_t& LinearizerMultidimensional<VectorLinearizerDataDimensions<LINEARIZER_DATA_TYPE> >::Iterator<triangle_indices_t>::get()
const
659 return this->linearizer->threadLinearizerMultidimensional[this->current_thread]->triangle_indices[this->current_thread_index];
664 int& LinearizerMultidimensional<VectorLinearizerDataDimensions<LINEARIZER_DATA_TYPE> >::Iterator<triangle_indices_t>::get_marker()
const
666 return this->linearizer->threadLinearizerMultidimensional[this->current_thread]->triangle_markers[this->current_thread_index];
669 template<
typename LinearizerDataDimensions>
677 for (
int i = 0; i < this->num_threads_used; i++)
678 iterator.thread_sizes.push_back(this->threadLinearizerMultidimensional[i]->vertex_count);
679 iterator.current_thread_size = iterator.thread_sizes[0];
680 iterator.check_zero_lengths();
683 template<
typename LinearizerDataDimensions>
691 for (
int i = 0; i < this->num_threads_used; i++)
692 iterator.thread_sizes.push_back(this->threadLinearizerMultidimensional[i]->triangle_count);
693 iterator.current_thread_size = iterator.thread_sizes[0];
694 iterator.check_zero_lengths();
697 template<
typename LinearizerDataDimensions>
705 for (
int i = 0; i < this->num_threads_used; i++)
706 iterator.thread_sizes.push_back(this->threadLinearizerMultidimensional[i]->edges_count);
707 iterator.current_thread_size = iterator.thread_sizes[0];
708 iterator.check_zero_lengths();
711 template<
typename LinearizerDataDimensions>
719 for (
int i = 0; i < this->num_threads_used; i++)
720 iterator.thread_sizes.push_back(this->threadLinearizerMultidimensional[i]->triangle_count);
721 iterator.current_thread_size = iterator.thread_sizes[0];
722 iterator.check_zero_lengths();
726 template<
typename LinearizerDataDimensions>
730 for (
int i = 0; i < this->num_threads_used; i++)
735 template<
typename LinearizerDataDimensions>
739 for (
int i = 0; i < this->num_threads_used; i++)
744 template<
typename LinearizerDataDimensions>
748 for (
int i = 0; i < this->num_threads_used; i++)
753 template<
typename LinearizerDataDimensions>
757 for (
int i = 0; i < this->num_threads_used; i++)
int get_edge_count() const
Edge count per all threads.
void check_data(MeshFunctionSharedPtr< double > *sln)
Before assembling.
void process_solution(MeshFunctionSharedPtr< double > sln, int item=H2D_FN_VAL_0)
int get_triangle_index_count() const
Triangle index count per all threads.
void lock_data() const
Internal.
void set_curvature_epsilon(double curvature_epsilon)
::xsd::cxx::tree::exception< char > exception
Root of the C++/Tree exception hierarchy.
bool user_xdisp
Information if user-supplied displacement functions have been provided.
Iterator< typename LinearizerDataDimensions::vertex_t > vertices_begin() const
Return the appropriate iterator pointing to the beginning.
File containing ThreadLinearizerMultidimensional class.
void save_solution_tecplot(MeshFunctionSharedPtr< double > sln, const char *filename, const char *quantity_name, int item=H2D_FN_VAL_0)
Save a MeshFunction (Solution, Filter) in Tecplot format.
void save_solution_vtk(MeshFunctionSharedPtr< double > sln, const char *filename, const char *quantity_name, bool mode_3D=true, int item=H2D_FN_VAL_0)
Save a MeshFunction (Solution, Filter) in VTK format.
int get_vertex_count() const
Vertex count per all threads.
ThreadLinearizerMultidimensional< LinearizerDataDimensions > ** threadLinearizerMultidimensional
Assembly data.
int3 triangle_indices_t
Typedefs used throughout the Linearizer functionality.
void free()
Free the instance.
MeshFunctionSharedPtr< double > xdisp
Displacement functions, default to ZeroFunctions, may be supplied by set_displacement();.
double get_curvature_epsilon() const
Get the 'curvature' epsilon determining the tolerance of catching the shape of curved elements...
void set_displacement(MeshFunctionSharedPtr< double > xdisp, MeshFunctionSharedPtr< double > ydisp, double dmult=1.0)
Set the displacement, i.e. set two functions that will deform the domain for visualization, in the x-direction, and the y-direction.
int get_triangle_count() const
Triangle per all threads.
void set_criterion(LinearizerCriterion criterion)
Iterator< typename LinearizerDataDimensions::edge_t > edges_begin() const
Return the appropriate iterator pointing to the beginning.
Iterator< triangle_indices_t > triangle_indices_begin() const
Return the appropriate iterator pointing to the beginning.
Simple Linearizer criterion - every element is refined exactly the same number of times...
Iterator< typename LinearizerDataDimensions::triangle_t > triangles_begin() const
Return the appropriate iterator pointing to the beginning.
void calc_vertices_aabb(double *min_x, double *max_x, double *min_y, double *max_y) const
Returns axis aligned bounding box (AABB) of vertices. Assumes lock.
Abstract class for criterion according to which the linearizer stops dividing elements at some point ...
bool end
The iterator has reached the end of the data.