Hermes2D  3.0
discrete_problem_integration_order_calculator.cpp
1 // This file is part of Hermes2D.
2 //
3 // Hermes2D is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, either version 2 of the License, or
6 // (at your option) any later version.
7 //
8 // Hermes2D is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with Hermes2D. If not, see <http://www.gnu.org/licenses/>.
15 
16 #include "discrete_problem/discrete_problem.h"
17 #include "discrete_problem/dg/discrete_problem_dg_assembler.h"
18 #include "function/exact_solution.h"
19 #include "global.h"
20 #include "quadrature/limit_order.h"
21 #include "mesh/traverse.h"
22 #include "space/space.h"
23 #include "shapeset/precalc.h"
24 #include "mesh/refmap.h"
25 #include "function/solution.h"
26 #include "neighbor_search.h"
27 #include "api2d.h"
28 #include <algorithm>
29 
31 
32 namespace Hermes
33 {
34  namespace Hermes2D
35  {
37  static GeomVol<Hermes::Ord> geom_order_vol;
38  static GeomSurf<Hermes::Ord> geom_order_surf;
39  static InterfaceGeom<Hermes::Ord> geom_order_interface;
41  double wt_order = 1.0;
42 
43  Func<Hermes::Ord> func_order[g_max_quad + 1] =
44  {
70  };
71 
72  template<typename Scalar>
74  selectiveAssembler(selectiveAssembler),
75  current_state(nullptr),
76  u_ext(nullptr)
77  {
78  }
79 
80  template<typename Scalar>
82  {
83  // Order set to constant.
84  if (current_wf->global_integration_order_set)
85  return current_wf->global_integration_order;
86 
87  // Order calculation.
88  int order = 0;
89 
90  // init - u_ext_func
91  Func<Hermes::Ord>** u_ext_func = this->init_u_ext_orders();
92  // init - ext
93  Func<Hermes::Ord>** ext_func = this->init_ext_orders(current_wf->ext, current_wf->u_ext_fn, u_ext_func);
94 
95  for (unsigned short current_mfvol_i = 0; current_mfvol_i < current_wf->mfvol.size(); current_mfvol_i++)
96  {
97  MatrixFormVol<Scalar>* current_mfvol = current_wf->mfvol[current_mfvol_i];
98  if (!selectiveAssembler->form_to_be_assembled(current_mfvol, current_state))
99  continue;
100  current_mfvol->wf = current_wf.get();
101  int orderTemp = calc_order_matrix_form(spaces, current_mfvol, current_refmaps, ext_func, u_ext_func);
102  if (order < orderTemp)
103  order = orderTemp;
104  }
105 
106  for (unsigned short current_vfvol_i = 0; current_vfvol_i < current_wf->vfvol.size(); current_vfvol_i++)
107  {
108  VectorFormVol<Scalar>* current_vfvol = current_wf->vfvol[current_vfvol_i];
109  if (!selectiveAssembler->form_to_be_assembled(current_vfvol, current_state))
110  continue;
111  current_vfvol->wf = current_wf.get();
112  int orderTemp = calc_order_vector_form(spaces, current_vfvol, current_refmaps, ext_func, u_ext_func);
113  if (order < orderTemp)
114  order = orderTemp;
115  }
116 
117  // Surface forms.
118  if (current_state->isBnd && (current_wf->mfsurf.size() > 0 || current_wf->vfsurf.size() > 0))
119  {
120  for (current_state->isurf = 0; current_state->isurf < current_state->rep->nvert; current_state->isurf++)
121  {
122  if (!current_state->bnd[current_state->isurf])
123  continue;
124 
125  // init - u_ext_func
126  Func<Hermes::Ord>** u_ext_funcSurf = this->init_u_ext_orders();
127 
128  // init - ext
129  Func<Hermes::Ord>** ext_funcSurf = this->init_ext_orders(current_wf->ext, current_wf->u_ext_fn, u_ext_func);
130 
131  for (unsigned short current_mfsurf_i = 0; current_mfsurf_i < current_wf->mfsurf.size(); current_mfsurf_i++)
132  {
133  MatrixFormSurf<Scalar>* current_mfsurf = current_wf->mfsurf[current_mfsurf_i];
134  if (!selectiveAssembler->form_to_be_assembled(current_mfsurf, current_state))
135  continue;
136  current_mfsurf->wf = current_wf.get();
137  int orderTemp = calc_order_matrix_form(spaces, current_mfsurf, current_refmaps, ext_funcSurf, u_ext_funcSurf);
138  if (order < orderTemp)
139  order = orderTemp;
140  }
141 
142  for (unsigned short current_vfsurf_i = 0; current_vfsurf_i < current_wf->vfsurf.size(); current_vfsurf_i++)
143  {
144  VectorFormSurf<Scalar>* current_vfsurf = current_wf->vfsurf[current_vfsurf_i];
145  if (!selectiveAssembler->form_to_be_assembled(current_vfsurf, current_state))
146  continue;
147 
148  current_vfsurf->wf = current_wf.get();
149  int orderTemp = calc_order_vector_form(spaces, current_vfsurf, current_refmaps, ext_funcSurf, u_ext_funcSurf);
150  if (order < orderTemp)
151  order = orderTemp;
152  }
153 
154  // deinit - u_ext_func
155  this->deinit_u_ext_orders(u_ext_funcSurf);
156 
157  // deinit - ext
158  this->deinit_ext_orders(ext_funcSurf);
159  }
160  }
161 
162  // deinit - u_ext_func
163  this->deinit_u_ext_orders(u_ext_func);
164 
165  // deinit - ext
166  this->deinit_ext_orders(ext_func);
167 
168  return order;
169  }
170 
171  template<typename Scalar>
172  template<typename MatrixFormType>
173  int DiscreteProblemIntegrationOrderCalculator<Scalar>::calc_order_matrix_form(const std::vector<SpaceSharedPtr<Scalar> >& spaces, MatrixFormType *form, RefMap** current_refmaps, Func<Hermes::Ord>** ext, Func<Hermes::Ord>** u_ext)
174  {
175  int order;
176 
177  Func<Hermes::Ord>** local_ext = ext;
178  // If the user supplied custom ext functions for this form.
179  if (form->ext.size() > 0)
180  local_ext = this->init_ext_orders(form->ext, (form->u_ext_fn.size() > 0 ? form->u_ext_fn : form->wf->u_ext_fn), u_ext);
181 
182  // Order of shape functions.
183  int max_order_j = spaces[form->j]->get_element_order(current_state->e[form->j]->id);
184  int max_order_i = spaces[form->i]->get_element_order(current_state->e[form->i]->id);
185  if (H2D_GET_V_ORDER(max_order_i) > H2D_GET_H_ORDER(max_order_i))
186  max_order_i = H2D_GET_V_ORDER(max_order_i);
187  else
188  max_order_i = H2D_GET_H_ORDER(max_order_i);
189  if (H2D_GET_V_ORDER(max_order_j) > H2D_GET_H_ORDER(max_order_j))
190  max_order_j = H2D_GET_V_ORDER(max_order_j);
191  else
192  max_order_j = H2D_GET_H_ORDER(max_order_j);
193 
194  for (unsigned int k = 0; k < current_state->rep->nvert; k++)
195  {
196  int eo = spaces[form->i]->get_edge_order(current_state->e[form->i], k);
197  if (eo > max_order_i)
198  max_order_i = eo;
199  eo = spaces[form->j]->get_edge_order(current_state->e[form->j], k);
200  if (eo > max_order_j)
201  max_order_j = eo;
202  }
203 
204  Func<Hermes::Ord>* ou = &func_order[max_order_j + (spaces[form->j]->shapeset->num_components > 1 ? 1 : 0)];
205  Func<Hermes::Ord>* ov = &func_order[max_order_i + (spaces[form->i]->shapeset->num_components > 1 ? 1 : 0)];
206 
207  // Total order of the vector form.
208  Hermes::Ord o;
209  if (dynamic_cast<MatrixFormVol<Scalar>*>(form))
210  o = (dynamic_cast<MatrixFormVol<Scalar>*>(form))->ord(1, &wt_order, u_ext, ou, ov, &geom_order_vol, local_ext);
211  else
212  o = (dynamic_cast<MatrixFormSurf<Scalar>*>(form))->ord(1, &wt_order, u_ext, ou, ov, &geom_order_surf, local_ext);
213 
214  adjust_order_to_refmaps(form, order, &o, current_refmaps);
215 
216  // Cleanup.
217  if (form->ext.size() > 0)
218  this->deinit_ext_orders(local_ext);
219 
220  return order;
221  }
222 
223  template<typename Scalar>
224  template<typename VectorFormType>
225  int DiscreteProblemIntegrationOrderCalculator<Scalar>::calc_order_vector_form(const std::vector<SpaceSharedPtr<Scalar> >& spaces, VectorFormType *form, RefMap** current_refmaps, Func<Hermes::Ord>** ext, Func<Hermes::Ord>** u_ext)
226  {
227  int order;
228 
229  Func<Hermes::Ord>** local_ext = ext;
230  // If the user supplied custom ext functions for this form.
231  if (form->ext.size() > 0)
232  local_ext = this->init_ext_orders(form->ext, (form->u_ext_fn.size() > 0 ? form->u_ext_fn : form->wf->u_ext_fn), u_ext);
233 
234  // Order of shape functions.
235  int max_order_i = spaces[form->i]->get_element_order(current_state->e[form->i]->id);
236  if (H2D_GET_V_ORDER(max_order_i) > H2D_GET_H_ORDER(max_order_i))
237  max_order_i = H2D_GET_V_ORDER(max_order_i);
238  else
239  max_order_i = H2D_GET_H_ORDER(max_order_i);
240 
241  for (unsigned int k = 0; k < current_state->rep->nvert; k++)
242  {
243  int eo = spaces[form->i]->get_edge_order(current_state->e[form->i], k);
244  if (eo > max_order_i)
245  max_order_i = eo;
246  }
247  Func<Hermes::Ord>* ov = &func_order[max_order_i + (spaces[form->i]->shapeset->num_components > 1 ? 1 : 0)];
248 
249  // Total order of the vector form.
250  Hermes::Ord o;
251  if (dynamic_cast<VectorFormVol<Scalar>*>(form))
252  o = (dynamic_cast<VectorFormVol<Scalar>*>(form))->ord(1, &wt_order, u_ext, ov, &geom_order_vol, local_ext);
253  else
254  o = (dynamic_cast<VectorFormSurf<Scalar>*>(form))->ord(1, &wt_order, u_ext, ov, &geom_order_surf, local_ext);
255 
256  adjust_order_to_refmaps(form, order, &o, current_refmaps);
257 
258  // Cleanup.
259  if (form->ext.size() > 0)
260  this->deinit_ext_orders(local_ext);
261 
262  return order;
263  }
264 
265  template<typename Scalar>
267  {
268  Func<Hermes::Ord>** u_ext_func = nullptr;
269  bool surface_form = (this->current_state->isurf > -1);
270  if (this->u_ext)
271  {
272  u_ext_func = new Func<Hermes::Ord>*[this->selectiveAssembler->spaces_size];
273 
274  for (int i = 0; i < this->selectiveAssembler->spaces_size; i++)
275  {
276  assert(this->u_ext[i]);
277 
278  if (this->u_ext[i]->get_active_element())
279  {
280  if (surface_form)
281  u_ext_func[i] = &func_order[this->u_ext[i]->get_edge_fn_order(this->current_state->isurf) + (this->u_ext[i]->get_num_components() > 1 ? 1 : 0)];
282  else
283  u_ext_func[i] = &func_order[this->u_ext[i]->get_fn_order() + (this->u_ext[i]->get_num_components() > 1 ? 1 : 0)];
284  }
285  else
286  u_ext_func[i] = &func_order[0];
287  }
288  }
289 
290  return u_ext_func;
291  }
292 
293  template<typename Scalar>
295  {
296  free_with_check(u_ext_func);
297  }
298 
299  template<typename Scalar>
301  {
302  int ext_size = ext.size();
303  int u_ext_fns_size = u_ext_fns.size();
304 
305  Func<Hermes::Ord>** ext_func = nullptr;
306 
307  bool surface_form = (this->current_state->isurf > -1);
308 
309  if (ext_size > 0 || u_ext_fns_size > 0)
310  {
311  ext_func = malloc_with_check<Func<Hermes::Ord>*>(ext_size + u_ext_fns_size);
312  for (unsigned short ext_i = 0; ext_i < ext.size(); ext_i++)
313  {
314  if (ext[ext_i])
315  {
316  if (ext[ext_i]->get_active_element())
317  {
318  if (surface_form)
319  ext_func[u_ext_fns_size + ext_i] = &func_order[ext[ext_i]->get_edge_fn_order(this->current_state->isurf) + (ext[ext_i]->get_num_components() > 1 ? 1 : 0)];
320  else
321  ext_func[u_ext_fns_size + ext_i] = &func_order[ext[ext_i]->get_fn_order() + (ext[ext_i]->get_num_components() > 1 ? 1 : 0)];
322  }
323  else
324  ext_func[u_ext_fns_size + ext_i] = nullptr;
325  }
326  else
327  ext_func[u_ext_fns_size + ext_i] = nullptr;
328  }
329 
330  for (int ext_i = 0; ext_i < u_ext_fns_size; ext_i++)
331  {
332  if (u_ext_fns[ext_i])
333  {
334  ext_func[ext_i] = &func_order[0];
335  u_ext_fns[ext_i]->ord(ext_func + u_ext_fns_size, u_ext_func, ext_func[ext_i]);
336  }
337  else
338  ext_func[ext_i] = nullptr;
339  }
340  }
341 
342  return ext_func;
343  }
344 
345  template<typename Scalar>
347  {
348  free_with_check(ext_func);
349  }
350 
351  template<typename Scalar>
352  void DiscreteProblemIntegrationOrderCalculator<Scalar>::adjust_order_to_refmaps(Form<Scalar> *form, int& order, Hermes::Ord* o, RefMap** current_refmaps)
353  {
354  // Increase due to reference map.
355  int coordinate = form->i;
356  order = current_refmaps[coordinate]->get_inv_ref_order();
357  order += o->get_order();
358  limit_order(order, current_refmaps[coordinate]->get_active_element()->get_mode());
359  }
360 
361  template<typename Scalar>
363  {
364  int inc = (fu->get_num_components() == 2) ? 1 : 0;
365  int central_order = fu->get_edge_fn_order(ns->active_edge) + inc;
366  int neighbor_order = fu->get_edge_fn_order(ns->neighbor_edge.local_num_of_edge) + inc;
367  return new DiscontinuousFunc<Ord>(&func_order[central_order], &func_order[neighbor_order]);
368  }
369 
370  template<typename Scalar>
372  NeighborSearch<Scalar>** neighbor_searches)
373  {
374  DiscontinuousFunc<Ord>** fake_ext_fns = new DiscontinuousFunc<Ord>*[ext.size()];
375  for (unsigned int j = 0; j < ext.size(); j++)
376  fake_ext_fns[j] = init_ext_fn_ord(DiscreteProblemDGAssembler<Scalar>::get_neighbor_search_ext(this->selectiveAssembler->get_weak_formulation(), neighbor_searches, j), ext[j]);
377 
378  return fake_ext_fns;
379  }
380 
381  template<typename Scalar>
382  template<typename FormType>
384  {
385  unsigned int prev_size = oi ? (this->rungeKutta ? this->RK_original_spaces_count : form->wf->get_neq() - form->u_ext_offset) : 0;
386 
387  if (oi)
388  {
389  for (int i = 0; i < prev_size; i++)
390  delete oi[i];
391  delete[] oi;
392  }
393 
394  int ext_size = form->ext.size() ? form->ext.size() : form->wf->ext.size();
395  int u_ext_fn_size = form->u_ext_fn.size() ? form->u_ext_fn.size() : form->wf->u_ext_fn.size();
396  if (oext)
397  {
398  for (int i = 0; i < ext_size + u_ext_fn_size; i++)
399  delete oext[i];
400  delete[] oext;
401  }
402  }
403 
404  template<typename Scalar>
405  int DiscreteProblemIntegrationOrderCalculator<Scalar>::calc_order_dg_matrix_form(const std::vector<SpaceSharedPtr<Scalar> > spaces, Traverse::State* current_state, MatrixFormDG<Scalar>* mfDG, RefMap** current_refmaps, Solution<Scalar>** current_u_ext, bool neighbor_supp_u, bool neighbor_supp_v, NeighborSearch<Scalar>** neighbor_searches)
406  {
407  NeighborSearch<Scalar>* nbs_u = neighbor_searches[mfDG->j];
408 
409  unsigned short prev_size = this->rungeKutta ? this->RK_original_spaces_count : mfDG->wf->get_neq() - mfDG->u_ext_offset;
410 
411  // Order to return.
412  int order = 0;
413 
414  DiscontinuousFunc<Hermes::Ord>** u_ext_ord = current_u_ext == nullptr ? nullptr : new DiscontinuousFunc<Hermes::Ord>*[this->rungeKutta ? this->RK_original_spaces_count : mfDG->wf->get_neq() - mfDG->u_ext_offset];
415 
416  if (current_u_ext)
417  for (unsigned short i = 0; i < prev_size; i++)
418  if (current_u_ext[i + mfDG->u_ext_offset])
419  u_ext_ord[i] = init_ext_fn_ord(nbs_u, current_u_ext[i + mfDG->u_ext_offset]);
420  else
421  u_ext_ord[i] = new DiscontinuousFunc<Ord>(&func_order[0], false, false);
422 
423  // Order of additional external functions.
424  DiscontinuousFunc<Ord>** ext_ord = nullptr;
425  std::vector<MeshFunctionSharedPtr<Scalar> > ext_ord_fns = mfDG->ext.size() ? mfDG->ext : mfDG->wf->ext;
426  if (ext_ord_fns.size() > 0)
427  ext_ord = init_ext_fns_ord(ext_ord_fns, neighbor_searches);
428 
429  // Order of shape functions.
430  int max_order_j = spaces[mfDG->j]->get_element_order(current_state->e[mfDG->j]->id);
431  int max_order_i = spaces[mfDG->i]->get_element_order(current_state->e[mfDG->i]->id);
432  if (H2D_GET_V_ORDER(max_order_i) > H2D_GET_H_ORDER(max_order_i))
433  max_order_i = H2D_GET_V_ORDER(max_order_i);
434  else
435  max_order_i = H2D_GET_H_ORDER(max_order_i);
436  if (H2D_GET_V_ORDER(max_order_j) > H2D_GET_H_ORDER(max_order_j))
437  max_order_j = H2D_GET_V_ORDER(max_order_j);
438  else
439  max_order_j = H2D_GET_H_ORDER(max_order_j);
440 
441  // Order of shape functions.
442  DiscontinuousFunc<Ord>* ou = new DiscontinuousFunc<Ord>(&func_order[max_order_j], neighbor_supp_u);
443  DiscontinuousFunc<Ord>* ov = new DiscontinuousFunc<Ord>(&func_order[max_order_i], neighbor_supp_v);
444 
445  // Order of geometric attributes (eg. for multiplication of a solution with coordinates, normals, etc.).
446 
447  // Total order of the matrix form.
448  Ord o = mfDG->ord(1, &wt_order, u_ext_ord, ou, ov, &geom_order_interface, ext_ord);
449 
450  adjust_order_to_refmaps(mfDG, order, &o, current_refmaps);
451 
452  // Cleanup.
453  deinit_ext_fns_ord(mfDG, u_ext_ord, ext_ord);
454 
455  delete ou;
456  delete ov;
457 
458  return order;
459  }
460 
461  template<typename Scalar>
462  int DiscreteProblemIntegrationOrderCalculator<Scalar>::calc_order_dg_vector_form(const std::vector<SpaceSharedPtr<Scalar> > spaces, Traverse::State* current_state, VectorFormDG<Scalar>* vfDG, RefMap** current_refmaps, Solution<Scalar>** current_u_ext, bool neighbor_supp_v, NeighborSearch<Scalar>** neighbor_searches)
463  {
464  NeighborSearch<Scalar>* nbs_u = neighbor_searches[vfDG->i];
465 
466  unsigned short prev_size = this->rungeKutta ? this->RK_original_spaces_count : vfDG->wf->get_neq() - vfDG->u_ext_offset;
467 
468  // Order to return.
469  int order = 0;
470 
471  DiscontinuousFunc<Hermes::Ord>** u_ext_ord = current_u_ext == nullptr ? nullptr : new DiscontinuousFunc<Hermes::Ord>*[this->rungeKutta ? this->RK_original_spaces_count : vfDG->wf->get_neq() - vfDG->u_ext_offset];
472 
473  if (current_u_ext)
474  for (unsigned short i = 0; i < prev_size; i++)
475  if (current_u_ext[i + vfDG->u_ext_offset])
476  u_ext_ord[i] = init_ext_fn_ord(nbs_u, current_u_ext[i + vfDG->u_ext_offset]);
477  else
478  u_ext_ord[i] = new DiscontinuousFunc<Ord>(&func_order[0], false, false);
479 
480  // Order of additional external functions.
481  DiscontinuousFunc<Ord>** ext_ord = nullptr;
482  std::vector<MeshFunctionSharedPtr<Scalar> > ext_ord_fns = vfDG->ext.size() ? vfDG->ext : vfDG->wf->ext;
483  if (ext_ord_fns.size() > 0)
484  ext_ord = init_ext_fns_ord(ext_ord_fns, neighbor_searches);
485 
486  // Order of shape functions.
487  int max_order_i = spaces[vfDG->i]->get_element_order(current_state->e[vfDG->i]->id);
488  if (H2D_GET_V_ORDER(max_order_i) > H2D_GET_H_ORDER(max_order_i))
489  max_order_i = H2D_GET_V_ORDER(max_order_i);
490  else
491  max_order_i = H2D_GET_H_ORDER(max_order_i);
492 
493  // Order of shape functions.
494  DiscontinuousFunc<Ord>* ov = new DiscontinuousFunc<Ord>(&func_order[max_order_i], neighbor_supp_v);
495 
496  // Total order of the matrix form.
497  Ord o = vfDG->ord(1, &wt_order, u_ext_ord, ov, &geom_order_interface, ext_ord);
498 
499  adjust_order_to_refmaps(vfDG, order, &o, current_refmaps);
500 
501  // Cleanup.
502  deinit_ext_fns_ord(vfDG, u_ext_ord, ext_ord);
503  delete ov;
504 
505  return order;
506  }
507 
508  template class HERMES_API DiscreteProblemIntegrationOrderCalculator < double > ;
510  }
511 }
double wt_order
"Fake" integration weight for order calculation.
std::vector< MeshFunctionSharedPtr< Scalar > > ext
External solutions.
Definition: weakform.h:328
Definition: adapt.h:24
int id
element id number
Definition: element.h:112
This class represents a function with jump discontinuity on an interface of two elements.
Definition: forms.h:335
Provides capabilities to (re-)assemble a matrix / vector only where necessary. See also Solver::keep_...
Used to pass the instances of Space around.
Definition: space.h:34
Common definitions for Hermes2D.
Abstract, base class for vector Surface form - i.e. VectorForm, where the integration is with respect...
Definition: weakform.h:48
Abstract, base class for vector DG form - i.e. linear Form, where the integration is with respect to ...
Definition: weakform.h:50
int get_inv_ref_order() const
Returns the increase in the integration order due to the reference map.
Definition: refmap.h:101
Abstract, base class for any form - i.e. integral in the weak formulation of (a system of) PDE By de...
Definition: weakform.h:43
Abstract, base class for matrix Surface form - i.e. MatrixForm, where the integration is with respect...
Definition: weakform.h:47
#define H2D_GET_H_ORDER(encoded_order)
Macros for combining quad horizontal and vertical encoded_orders.
Definition: global.h:98
Used to pass the instances of WeakForm around.
Definition: weakform.h:55
Abstract, base class for matrix Volumetric form - i.e. MatrixForm, where the integration is with resp...
Definition: weakform.h:45
Represents the reference mapping.
Definition: refmap.h:40
This class characterizes a neighborhood of a given edge in terms of adjacent elements and provides me...
Represents the solution of a PDE.
Definition: api2d.h:35
Abstract, base class for matrix DG form - i.e. bilinear form, where the integration is with respect t...
Definition: weakform.h:49
bool form_to_be_assembled(MatrixForm< Scalar > *form, Traverse::State *current_state)
Decides if the form will be assembled on this State.
Abstract, base class for vector Volumetric form - i.e. VectorForm, where the integration is with resp...
Definition: weakform.h:46