Hermes2D  3.0
forms.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 
17 
18 #include "forms.h"
19 #include "api2d.h"
20 #include <complex>
21 
22 namespace Hermes
23 {
24  namespace Hermes2D
25  {
26  Func<double>::Func() : np(-1), nc(-1)
27  {
28  }
29 
30  Func<double>::Func(int np, int nc) : np(np), nc(nc)
31  {
32  }
33 
34  Func<std::complex<double> >::Func() : np(-1), nc(-1)
35  {
36  }
37 
38  Func<std::complex<double> >::Func(int np, int nc) : np(np), nc(nc)
39  {
40  }
41 
42  Func<Hermes::Ord>::Func(const int order) : order(order)
43  {
44  Hermes::Ord d(order);
45  Hermes::Ord d1(order > 1 ? order - 1 : order);
46 
47  this->val = this->val0 = this->val1 = d;
48  this->dx = this->dy = this->curl = this->div = d1;
49 
50 #ifdef H2D_USE_SECOND_DERIVATIVES
51  Hermes::Ord d2(std::min(0, order - 2));
52  this->laplace = d2;
53 #endif
54  }
55 
57  {
58  if (this->np != func->np)
59  throw Hermes::Exceptions::Exception("Unable to subtract a function due to a different number of integration points (this: %d, other: %d)", np, func->np);
60  if (nc != func->nc)
61  throw Hermes::Exceptions::Exception("Unable to subtract a function due to a different number of components (this: %d, other: %d)", nc, func->nc);
62 
63  subtract(this->val, func->val);
64  subtract(this->dx, func->dx);
65  subtract(this->dy, func->dy);
66 
67 #ifdef H2D_USE_SECOND_DERIVATIVES
68  subtract(this->laplace, func->laplace);
69 #endif
70 
71  if (nc > 1)
72  {
73  subtract(this->val0, func->val0);
74  subtract(this->val1, func->val1);
75  subtract(this->curl, func->curl);
76  subtract(this->div, func->div);
77  }
78  };
79 
80  void Func<std::complex<double> >::subtract(Func<std::complex<double> >* func)
81  {
82  if (this->np != func->np)
83  throw Hermes::Exceptions::Exception("Unable to subtract a function due to a different number of integration points (this: %d, other: %d)", np, func->np);
84  if (nc != func->nc)
85  throw Hermes::Exceptions::Exception("Unable to subtract a function due to a different number of components (this: %d, other: %d)", nc, func->nc);
86 
87  subtract(this->val, func->val);
88  subtract(this->dx, func->dx);
89  subtract(this->dy, func->dy);
90 
91 #ifdef H2D_USE_SECOND_DERIVATIVES
92  subtract(this->laplace, func->laplace);
93 #endif
94 
95  if (nc > 1)
96  {
97  subtract(this->val0, func->val0);
98  subtract(this->val1, func->val1);
99  subtract(this->curl, func->curl);
100  subtract(this->div, func->div);
101  }
102  };
103 
104  void Func<double>::subtract(double* attribute, double* other_attribute)
105  {
106  if (attribute != nullptr && other_attribute != nullptr)
107  {
108  for (int i = 0; i < this->np; i++)
109  attribute[i] -= other_attribute[i];
110  }
111  }
112 
113  void Func<std::complex<double> >::subtract(std::complex<double> * attribute, std::complex<double> * other_attribute)
114  {
115  if (attribute != nullptr && other_attribute != nullptr)
116  {
117  for (int i = 0; i < this->np; i++)
118  attribute[i] -= other_attribute[i];
119  }
120  }
121 
123  {
124  if (this->np != func->np)
125  throw Hermes::Exceptions::Exception("Unable to add a function due to a different number of integration points (this: %d, other: %d)", np, func->np);
126  if (nc != func->nc)
127  throw Hermes::Exceptions::Exception("Unable to add a function due to a different number of components (this: %d, other: %d)", nc, func->nc);
128 
129  add(this->val, func->val);
130  add(this->dx, func->dx);
131  add(this->dy, func->dy);
132 
133 #ifdef H2D_USE_SECOND_DERIVATIVES
134  add(this->laplace, func->laplace);
135 #endif
136 
137  if (nc > 1)
138  {
139  add(this->val0, func->val0);
140  add(this->val1, func->val1);
141  add(this->curl, func->curl);
142  add(this->div, func->div);
143  }
144  };
145 
146 #ifdef H2D_USE_SECOND_DERIVATIVES
147  template<>
148 #endif
149  void Func<std::complex<double> >::add(Func<std::complex<double> >* func)
150  {
151  if (this->np != func->np)
152  throw Hermes::Exceptions::Exception("Unable to add a function due to a different number of integration points (this: %d, other: %d)", np, func->np);
153  if (nc != func->nc)
154  throw Hermes::Exceptions::Exception("Unable to add a function due to a different number of components (this: %d, other: %d)", nc, func->nc);
155 
156  add(this->val, func->val);
157  add(this->dx, func->dx);
158  add(this->dy, func->dy);
159 
160 #ifdef H2D_USE_SECOND_DERIVATIVES
161  add(this->laplace, func->laplace);
162 #endif
163 
164  if (nc > 1)
165  {
166  add(this->val0, func->val0);
167  add(this->val1, func->val1);
168  add(this->curl, func->curl);
169  add(this->div, func->div);
170  }
171  };
172 
173  void Func<double>::add(double* attribute, double* other_attribute)
174  {
175  if (attribute != nullptr && other_attribute != nullptr)
176  {
177  for (int i = 0; i < this->np; i++)
178  attribute[i] += other_attribute[i];
179  }
180  }
181 
182  void Func<std::complex<double> >::add(std::complex<double> * attribute, std::complex<double> * other_attribute)
183  {
184  if (attribute != nullptr && other_attribute != nullptr)
185  {
186  for (int i = 0; i < this->np; i++)
187  attribute[i] += other_attribute[i];
188  }
189  }
190 
191  template<typename T>
192  DiscontinuousFunc<T>::DiscontinuousFunc(Func<T>* fn, bool support_on_neighbor, bool reverse) :
193  Func<T>(fn->np, fn->nc), fn_central(nullptr), fn_neighbor(nullptr), reverse_neighbor_side(reverse)
194  {
195  if (fn == nullptr)
196  throw Hermes::Exceptions::Exception("Invalid arguments to DiscontinuousFunc constructor.");
197  if (support_on_neighbor)
198  {
199  fn_neighbor = fn;
201  {
202  this->val_neighbor = malloc_with_check<DiscontinuousFunc<T>, T>(this->np, this);
203  this->dx_neighbor = malloc_with_check<DiscontinuousFunc<T>, T>(this->np, this);
204  this->dy_neighbor = malloc_with_check<DiscontinuousFunc<T>, T>(this->np, this);
205  for (int i = 0; i < this->np; i++)
206  {
207  this->val_neighbor[i] = fn->val[this->np - i - 1];
208  this->dx_neighbor[i] = fn->dx[this->np - i - 1];
209  this->dy_neighbor[i] = fn->dy[this->np - i - 1];
210  }
211  }
212  else
213  {
214  this->val_neighbor = fn->val;
215  this->dx_neighbor = fn->dx;
216  this->dy_neighbor = fn->dy;
217  }
218 
219  this->val = this->dx = this->dy = nullptr;
220  }
221  else
222  {
223  this->fn_central = fn;
224  this->val = fn->val;
225  this->dx = fn->dx;
226  this->dy = fn->dy;
227  this->val_neighbor = this->dx_neighbor = this->dy_neighbor = nullptr;
228  }
229  }
230 
231  template<typename T>
233  Func<T>(fn_c->np, fn_c->nc), fn_central(fn_c), fn_neighbor(fn_n), reverse_neighbor_side(reverse)
234  {
236  {
237  this->val_neighbor = malloc_with_check<DiscontinuousFunc<T>, T>(this->np, this);
238  this->dx_neighbor = malloc_with_check<DiscontinuousFunc<T>, T>(this->np, this);
239  this->dy_neighbor = malloc_with_check<DiscontinuousFunc<T>, T>(this->np, this);
240  for (int i = 0; i < this->np; i++)
241  {
242  this->val_neighbor[i] = fn_neighbor->val[this->np - i - 1];
243  this->dx_neighbor[i] = fn_neighbor->dx[this->np - i - 1];
244  this->dy_neighbor[i] = fn_neighbor->dy[this->np - i - 1];
245  }
246  }
247  else
248  {
249  this->val_neighbor = fn_neighbor->val;
250  this->dx_neighbor = fn_neighbor->dx;
251  this->dy_neighbor = fn_neighbor->dy;
252  }
253  this->val = fn_central->val;
254  this->dx = fn_central->dx;
255  this->dy = fn_central->dy;
256  }
257 
258  DiscontinuousFunc<Ord>::DiscontinuousFunc(Func<Ord>* fn, bool support_on_neighbor, bool reverse) : Func<Ord>(fn->order),
259  fn_central(nullptr), fn_neighbor(nullptr), reverse_neighbor_side(reverse)
260  {
261  if (fn == nullptr)
262  throw Hermes::Exceptions::Exception("Invalid arguments to DiscontinuousFunc constructor.");
263  if (support_on_neighbor)
264  {
265  this->fn_neighbor = fn;
266  this->val_neighbor = fn->val;
267  this->dx_neighbor = fn->dx;
268  this->dy_neighbor = fn->dy;
269  }
270  else
271  {
272  this->fn_central = fn;
273  this->val = fn->val;
274  this->dx = fn->dx;
275  this->dy = fn->dy;
276  }
277  }
278 
279  DiscontinuousFunc<Ord>::DiscontinuousFunc(Func<Ord>* fn_c, Func<Ord>* fn_n, bool reverse) : Func<Ord>(std::max(fn_c->order, fn_n->order)),
280  fn_central(fn_c), fn_neighbor(fn_n), reverse_neighbor_side(reverse)
281  {
282  this->val_neighbor = fn_neighbor->val;
283  this->dx_neighbor = fn_neighbor->dx;
284  this->dy_neighbor = fn_neighbor->dy;
285 
286  this->val = fn_central->val;
287  this->dx = fn_central->dx;
288  this->dy = fn_central->dy;
289  }
290 
291  template<typename T>
293  {
294  if (fn_central != nullptr && func.fn_central != nullptr)
295  fn_central->subtract(func.fn_central);
296  if (fn_neighbor != nullptr && func.fn_neighbor != nullptr)
297  {
298  fn_neighbor->subtract(func.fn_neighbor);
299  if (reverse_neighbor_side)
300  {
301  Func<T>::subtract(this->val_neighbor, func.val_neighbor);
302  Func<T>::subtract(this->dx_neighbor, func.dx_neighbor);
303  Func<T>::subtract(this->dy_neighbor, func.dy_neighbor);
304  }
305  }
306  }
307 
308  template<typename T>
309  DiscontinuousFunc<T>::~DiscontinuousFunc()
310  {
311  free();
312  }
313 
314  template<typename T>
315  void DiscontinuousFunc<T>::free()
316  {
317  if (fn_central != nullptr)
318  {
319  delete fn_central;
320  fn_central = nullptr;
321  }
322  if (fn_neighbor != nullptr)
323  {
324  if (reverse_neighbor_side)
325  {
326  free_with_check(this->val_neighbor);
327  free_with_check(this->dx_neighbor);
328  free_with_check(this->dy_neighbor);
329  }
330  delete fn_neighbor;
331  fn_neighbor = nullptr;
332  }
333  }
334 
335  template<>
336  double GeomVol<double>::get_diam_approximation(unsigned char n)
337  {
338  double x_min = std::numeric_limits<double>::max(),
339  x_max = std::numeric_limits<double>::min(),
340  y_min = std::numeric_limits<double>::max(),
341  y_max = std::numeric_limits<double>::min();
342 
343  for (unsigned char i = 0; i < n; i++)
344  {
345  if (this->x[i] < x_min)
346  x_min = this->x[i];
347  if (this->x[i] > x_max)
348  x_max = this->x[i];
349 
350  if (this->y[i] < y_min)
351  y_min = this->y[i];
352  if (this->y[i] > y_max)
353  y_max = this->y[i];
354  }
355 
356  return std::sqrt((x_max - x_min) * (x_max - x_min) + (y_max - y_min) * (y_max - y_min));
357  }
358 
359  template<>
360  double GeomVol<double>::get_area(unsigned char n, double* wt)
361  {
362  double area = 0.;
363  for (unsigned char i = 0; i < n; i++)
364  area += wt[i];
365  return area;
366  }
367 
368  template<typename T>
369  InterfaceGeom<T>::InterfaceGeom(GeomSurf<T>* geom, Element* central_el, Element* neighb_el) : central_el(central_el), neighb_el(neighb_el)
370  {
371  // Let this class expose the standard Geom interface.
372  this->elem_marker = geom->elem_marker;
373  this->edge_marker = geom->edge_marker;
374  this->isurf = geom->isurf;
375  this->orientation = geom->orientation;
376  this->x = geom->x;
377  this->y = geom->y;
378  this->tx = geom->tx;
379  this->ty = geom->ty;
380  this->nx = geom->nx;
381  this->ny = geom->ny;
382  this->wrapped_geom = geom;
383  }
384 
385  template<>
386  double InterfaceGeom<double>::get_diam_approximation(unsigned char n)
387  {
388  double x_min = std::numeric_limits<double>::max(),
389  x_max = std::numeric_limits<double>::min(),
390  y_min = std::numeric_limits<double>::max(),
391  y_max = std::numeric_limits<double>::min();
392 
393  for (unsigned char i = 0; i < n; i++)
394  {
395  if (this->x[i] < x_min)
396  x_min = this->x[i];
397  if (this->x[i] > x_max)
398  x_max = this->x[i];
399 
400  if (this->y[i] < y_min)
401  y_min = this->y[i];
402  if (this->y[i] > y_max)
403  y_max = this->y[i];
404  }
405 
406  return std::sqrt((x_max - x_min) * (x_max - x_min) + (y_max - y_min) * (y_max - y_min));
407  }
408 
409  template<>
410  double InterfaceGeom<double>::get_area(unsigned char n, double* wt)
411  {
412  double area = 0.;
413  for (unsigned char i = 0; i < n; i++)
414  area += wt[i];
415  return area;
416  }
417 
418  GeomVol<double>* init_geom_vol(RefMap *rm, const int order)
419  {
421  init_geom_vol_allocated(*e, rm, order);
422  return e;
423  }
424 
425  void init_geom_vol_allocated(GeomVol<double>& geom, RefMap *rm, const int order)
426  {
427  Element* element = rm->get_active_element();
428  ElementMode2D mode = element->get_mode();
429  geom.id = element->id;
430  geom.elem_marker = element->marker;
431  Quad2D* quad = rm->get_quad_2d();
432  unsigned char np = quad->get_num_points(order, mode);
433  memcpy(geom.x, rm->get_phys_x(order), np * sizeof(double));
434  memcpy(geom.y, rm->get_phys_y(order), np * sizeof(double));
435  }
436 
437  GeomSurf<double>* init_geom_surf(RefMap *rm, unsigned char isurf, int marker, const int order, double3*& tan)
438  {
440  init_geom_surf_allocated(*e, rm, isurf, marker, order, tan);
441  return e;
442  }
443 
444  void init_geom_surf_allocated(GeomSurf<double>& geom, RefMap *rm, unsigned char isurf, int marker, const int order, double3*& tan)
445  {
446  Element* element = rm->get_active_element();
447  ElementMode2D mode = element->get_mode();
448 
449  geom.edge_marker = marker;
450  geom.elem_marker = element->marker;
451  geom.isurf = isurf;
452 
453  tan = rm->get_tangent(isurf, order);
454 
455  Quad2D* quad = rm->get_quad_2d();
456  unsigned char np = quad->get_num_points(order, mode);
457 
458  memcpy(geom.x, rm->get_phys_x(order), np * sizeof(double));
459  memcpy(geom.y, rm->get_phys_y(order), np * sizeof(double));
460 
461  for (int i = 0; i < np; i++)
462  {
463  geom.tx[i] = tan[i][0]; geom.ty[i] = tan[i][1];
464  geom.nx[i] = tan[i][1]; geom.ny[i] = -tan[i][0];
465  }
466  geom.orientation = rm->get_active_element()->get_edge_orientation(isurf);
467  }
468 
469  Func<double>* init_fn(PrecalcShapeset *fu, RefMap *rm, const int order)
470  {
471  Func<double>* u = preallocate_fn<double>();
472 
473  init_fn_preallocated(u, fu, rm, order);
474 
475  return u;
476  }
477 
478  template<typename Scalar>
480  {
481  Func<Scalar>* u = preallocate_fn<Scalar>();
482 
483  init_fn_preallocated(u, fu, order);
484 
485  return u;
486  }
487 
488  template<typename Scalar>
489  Func<Scalar>* preallocate_fn(pj_pool_t* memoryPool)
490  {
491  if (memoryPool)
492  return (Func<Scalar>*)pj_pool_alloc(memoryPool, sizeof(Func<Scalar>));
493  else
494  return new Func<Scalar>();
495  }
496 
497  void init_fn_preallocated(Func<double>* u, PrecalcShapeset *fu, RefMap *rm, const int order)
498  {
499  SpaceType space_type = fu->get_space_type();
500 
501 #ifdef H2D_USE_SECOND_DERIVATIVES
502  if (space_type == HERMES_H1_SPACE || space_type == HERMES_L2_SPACE)
503  fu->set_quad_order(order, H2D_FN_ALL);
504  else
505  fu->set_quad_order(order);
506 #else
507  fu->set_quad_order(order);
508 #endif
509 
510  int nc = fu->get_num_components();
511  unsigned char np = fu->get_quad_2d()->get_num_points(order, fu->get_active_element()->get_mode());
512  u->np = np;
513  u->nc = nc;
514 
515  // H1 & L2 space.
516  if (space_type == HERMES_H1_SPACE || space_type == HERMES_L2_SPACE)
517  {
518  const double *fn = fu->get_fn_values();
519  const double *dx = fu->get_dx_values();
520  const double *dy = fu->get_dy_values();
521 
522 #ifdef H2D_USE_SECOND_DERIVATIVES
523  const double *dxx = fu->get_dxx_values();
524  const double *dxy = fu->get_dxy_values();
525  const double *dyy = fu->get_dyy_values();
526 #endif
527 
528  if (rm->is_jacobian_const())
529  {
530  double const_inv_ref_map00 = rm->get_const_inv_ref_map()[0][0][0];
531  double const_inv_ref_map01 = rm->get_const_inv_ref_map()[0][0][1];
532  double const_inv_ref_map10 = rm->get_const_inv_ref_map()[0][1][0];
533  double const_inv_ref_map11 = rm->get_const_inv_ref_map()[0][1][1];
534  for (int i = 0; i < np; i++)
535  {
536  u->val[i] = fn[i];
537  u->dx[i] = (dx[i] * const_inv_ref_map00 + dy[i] * const_inv_ref_map01);
538  u->dy[i] = (dx[i] * const_inv_ref_map10 + dy[i] * const_inv_ref_map11);
539  }
540 #ifdef H2D_USE_SECOND_DERIVATIVES
541  double3x2 *mm;
542  mm = rm->get_second_ref_map(order);
543  for (int i = 0; i < np; i++, mm++)
544  {
545  u->val[i] = fn[i];
546  u->dx[i] = (dx[i] * const_inv_ref_map00 + dy[i] * const_inv_ref_map01);
547  u->dy[i] = (dx[i] * const_inv_ref_map10 + dy[i] * const_inv_ref_map11);
548 
549  double axx = (Hermes::sqr(const_inv_ref_map00) + Hermes::sqr(const_inv_ref_map10));
550  double ayy = (Hermes::sqr(const_inv_ref_map01) + Hermes::sqr(const_inv_ref_map11));
551  double axy = 2.0 * (const_inv_ref_map00 * const_inv_ref_map01 + const_inv_ref_map10 * const_inv_ref_map11);
552  double ax = (*mm)[0][0] + (*mm)[2][0];
553  double ay = (*mm)[0][1] + (*mm)[2][1];
554  u->laplace[i] = (dx[i] * ax + dy[i] * ay + dxx[i] * axx + dxy[i] * axy + dyy[i] * ayy);
555  }
556 #endif
557  }
558  else
559  {
560  double2x2 *m = rm->get_inv_ref_map(order);
561 
562 #ifdef H2D_USE_SECOND_DERIVATIVES
563  double3x2 *mm;
564  mm = rm->get_second_ref_map(order);
565  for (int i = 0; i < np; i++, m++, mm++)
566  {
567  u->val[i] = fn[i];
568  u->dx[i] = (dx[i] * (*m)[0][0] + dy[i] * (*m)[0][1]);
569  u->dy[i] = (dx[i] * (*m)[1][0] + dy[i] * (*m)[1][1]);
570 
571  double axx = (Hermes::sqr((*m)[0][0]) + Hermes::sqr((*m)[1][0]));
572  double ayy = (Hermes::sqr((*m)[0][1]) + Hermes::sqr((*m)[1][1]));
573  double axy = 2.0 * ((*m)[0][0] * (*m)[0][1] + (*m)[1][0] * (*m)[1][1]);
574  double ax = (*mm)[0][0] + (*mm)[2][0];
575  double ay = (*mm)[0][1] + (*mm)[2][1];
576  u->laplace[i] = (dx[i] * ax + dy[i] * ay + dxx[i] * axx + dxy[i] * axy + dyy[i] * ayy);
577  }
578 #else
579  for (int i = 0; i < np; i++, m++)
580  {
581  u->val[i] = fn[i];
582  u->dx[i] = (dx[i] * (*m)[0][0] + dy[i] * (*m)[0][1]);
583  u->dy[i] = (dx[i] * (*m)[1][0] + dy[i] * (*m)[1][1]);
584  }
585 #endif
586  }
587  }
588  // Hcurl space.
589  else if (space_type == HERMES_HCURL_SPACE)
590  {
591  const double *fn0 = fu->get_fn_values(0);
592  const double *fn1 = fu->get_fn_values(1);
593  const double *dx1 = fu->get_dx_values(1);
594  const double *dy0 = fu->get_dy_values(0);
595  if (rm->is_jacobian_const())
596  {
597  double const_inv_ref_map00 = rm->get_const_inv_ref_map()[0][0][0];
598  double const_inv_ref_map01 = rm->get_const_inv_ref_map()[0][0][1];
599  double const_inv_ref_map10 = rm->get_const_inv_ref_map()[0][1][0];
600  double const_inv_ref_map11 = rm->get_const_inv_ref_map()[0][1][1];
601  double determinant = (const_inv_ref_map00 * const_inv_ref_map11 - const_inv_ref_map10 * const_inv_ref_map01);
602  for (int i = 0; i < np; i++)
603  {
604  u->val0[i] = (fn0[i] * const_inv_ref_map00 + fn1[i] * const_inv_ref_map01);
605  u->val1[i] = (fn0[i] * const_inv_ref_map10 + fn1[i] * const_inv_ref_map11);
606  u->curl[i] = determinant * (dx1[i] - dy0[i]);
607  }
608  }
609  else
610  {
611  double2x2* m = rm->get_inv_ref_map(order);
612  for (int i = 0; i < np; i++, m++)
613  {
614  u->val0[i] = (fn0[i] * (*m)[0][0] + fn1[i] * (*m)[0][1]);
615  u->val1[i] = (fn0[i] * (*m)[1][0] + fn1[i] * (*m)[1][1]);
616  u->curl[i] = ((*m)[0][0] * (*m)[1][1] - (*m)[1][0] * (*m)[0][1]) * (dx1[i] - dy0[i]);
617  }
618  }
619  }
620  // Hdiv space.
621  else if (space_type == HERMES_HDIV_SPACE)
622  {
623  const double *fn0 = fu->get_fn_values(0);
624  const double *fn1 = fu->get_fn_values(1);
625  const double *dx0 = fu->get_dx_values(0);
626  const double *dy1 = fu->get_dy_values(1);
627  if (rm->is_jacobian_const())
628  {
629  double const_inv_ref_map00 = rm->get_const_inv_ref_map()[0][0][0];
630  double const_inv_ref_map01 = rm->get_const_inv_ref_map()[0][0][1];
631  double const_inv_ref_map10 = rm->get_const_inv_ref_map()[0][1][0];
632  double const_inv_ref_map11 = rm->get_const_inv_ref_map()[0][1][1];
633  double determinant = (const_inv_ref_map00 * const_inv_ref_map11 - const_inv_ref_map10 * const_inv_ref_map01);
634 
635  for (int i = 0; i < np; i++)
636  {
637  u->val0[i] = (fn0[i] * const_inv_ref_map11 - fn1[i] * const_inv_ref_map10);
638  u->val1[i] = (-fn0[i] * const_inv_ref_map01 + fn1[i] * const_inv_ref_map00);
639  u->div[i] = determinant * (dx0[i] + dy1[i]);
640  }
641  }
642  else
643  {
644  double2x2* m = rm->get_inv_ref_map(order);
645  for (int i = 0; i < np; i++, m++)
646  {
647  u->val0[i] = (fn0[i] * (*m)[1][1] - fn1[i] * (*m)[1][0]);
648  u->val1[i] = (-fn0[i] * (*m)[0][1] + fn1[i] * (*m)[0][0]);
649  u->div[i] = ((*m)[0][0] * (*m)[1][1] - (*m)[1][0] * (*m)[0][1]) * (dx0[i] + dy1[i]);
650  }
651  }
652  }
653  else
654  throw Hermes::Exceptions::Exception("Wrong space type - space has to be either H1, Hcurl, Hdiv or L2");
655  }
656 
657  template<typename Scalar>
659  {
660  // Sanity checks.
661  if (fu == nullptr)
662  throw Hermes::Exceptions::Exception("nullptr MeshFunction in Func<Scalar>*::init_fn().");
663  if (fu->get_mesh() == nullptr)
664  throw Hermes::Exceptions::Exception("Uninitialized MeshFunction used.");
665 
666  Quad2D* quad = fu->get_quad_2d();
667 #ifdef H2D_USE_SECOND_DERIVATIVES
668  Solution<Scalar>* sln = dynamic_cast<Solution<Scalar>*>(fu);
669  if (sln)
670  {
671  if ((sln->get_space_type() == HERMES_H1_SPACE || sln->get_space_type() == HERMES_L2_SPACE) && sln->get_type() != HERMES_EXACT)
672  fu->set_quad_order(order, H2D_FN_ALL);
673  else
674  fu->set_quad_order(order);
675  }
676  else
677  fu->set_quad_order(order);
678 #else
679  fu->set_quad_order(order);
680 #endif
681  int nc = fu->get_num_components();
682  unsigned char np = quad->get_num_points(order, fu->get_active_element()->get_mode());
683  u->np = np;
684  u->nc = nc;
685 
686  if (u->nc == 1)
687  {
688  memcpy(u->val, fu->get_fn_values(), np * sizeof(Scalar));
689  memcpy(u->dx, fu->get_dx_values(), np * sizeof(Scalar));
690  memcpy(u->dy, fu->get_dy_values(), np * sizeof(Scalar));
691 
692 #ifdef H2D_USE_SECOND_DERIVATIVES
693  if (sln && (sln->get_space_type() == HERMES_H1_SPACE || sln->get_space_type() == HERMES_L2_SPACE) && sln->get_type() != HERMES_EXACT)
694  {
695  Scalar *dxx = fu->get_dxx_values();
696  Scalar *dyy = fu->get_dyy_values();
697  for (int i = 0; i < np; i++)
698  u->laplace[i] = dxx[i] + dyy[i];
699  }
700 #endif
701  }
702  else
703  {
704  memcpy(u->val0, fu->get_fn_values(0), np * sizeof(Scalar));
705  memcpy(u->val1, fu->get_fn_values(1), np * sizeof(Scalar));
706 
707  const Scalar *dx1 = fu->get_dx_values(1);
708  const Scalar *dy0 = fu->get_dy_values(0);
709  for (int i = 0; i < np; i++)
710  u->curl[i] = dx1[i] - dy0[i];
711 
712  const Scalar *dx0 = fu->get_dx_values(0);
713  const Scalar *dy1 = fu->get_dy_values(1);
714  for (int i = 0; i < np; i++)
715  u->div[i] = dx0[i] + dy1[i];
716  }
717  }
718 
719  template<typename Scalar>
720  void init_fn_preallocated(Func<Scalar>* u, UExtFunction<Scalar>* fu, Func<Scalar>** ext, Func<Scalar>** u_ext, const int order, Geom<double>* geometry, ElementMode2D mode)
721  {
722  // Sanity check.
723  if (fu == nullptr)
724  throw Hermes::Exceptions::Exception("nullptr UExtFunction in Func<Scalar>*::init_fn().");
725 
726  Quad2D* quad = &g_quad_2d_std;
727  unsigned char np = quad->get_num_points(order, mode);
728 
729  fu->value(np, ext, u_ext, u, geometry);
730  }
731 
732  template<typename Scalar>
733  Func<Scalar>* init_zero_fn(ElementMode2D mode, int order, Quad2D* quad, int nc)
734  {
735  if (quad == nullptr)
736  quad = &g_quad_2d_std;
737 
738  unsigned char np = quad->get_num_points(order, mode);
739  Func<Scalar>* u = new Func<Scalar>(np, nc);
740 
741  if (nc == 1)
742  {
743  memset(u->val, 0, np * sizeof(Scalar));
744  memset(u->dx, 0, np * sizeof(Scalar));
745  memset(u->dy, 0, np * sizeof(Scalar));
746  }
747  else if (nc == 2)
748  {
749  memset(u->val0, 0, np * sizeof(Scalar));
750  memset(u->val1, 0, np * sizeof(Scalar));
751  memset(u->curl, 0, np * sizeof(Scalar));
752  memset(u->div, 0, np * sizeof(Scalar));
753  }
754  return u;
755  }
756 
757  template<typename Scalar>
758  Func<Scalar>* init_fn(UExtFunction<Scalar>* fu, Func<Scalar>** ext, Func<Scalar>** u_ext, const int order, Geom<double>* geometry, ElementMode2D mode)
759  {
760  int nc = 1;
761  Quad2D* quad = &g_quad_2d_std;
762 
763  unsigned char np = quad->get_num_points(order, mode);
764  Func<Scalar>* u = new Func<Scalar>(np, nc);
765 
766  // Sanity check.
767  if (fu == nullptr)
768  throw Hermes::Exceptions::Exception("nullptr UExtFunction in Func<Scalar>*::init_fn().");
769 
770  fu->value(np, ext, u_ext, u, geometry);
771 
772  return u;
773  }
774 
775  template HERMES_API Func<double>* init_fn(MeshFunction<double>* fu, const int order);
776  template HERMES_API Func<std::complex<double> >* init_fn(MeshFunction<std::complex<double> >* fu, const int order);
777 
778  template HERMES_API Func<double>* preallocate_fn(pj_pool_t* memoryPool);
779  template HERMES_API Func<std::complex<double> >* preallocate_fn(pj_pool_t* memoryPool);
780 
781  template HERMES_API void init_fn_preallocated(Func<double>* u, MeshFunction<double>* fu, const int order);
782  template HERMES_API void init_fn_preallocated(Func<std::complex<double> >* u, MeshFunction<std::complex<double> >* fu, const int order);
783 
784  template HERMES_API void init_fn_preallocated(Func<double>* u, UExtFunction<double>* fu, Func<double>** ext, Func<double>** u_ext, const int order, Geom<double>* geometry, ElementMode2D mode);
785  template HERMES_API void init_fn_preallocated(Func<std::complex<double> >* u, UExtFunction<std::complex<double> >* fu, Func<std::complex<double> >** ext, Func<std::complex<double> >** u_ext, const int order, Geom<double>* geometry, ElementMode2D mode);
786 
787  template HERMES_API Func<double>* init_zero_fn(ElementMode2D mode, int order, Quad2D* quad_2d, int nc);
788  template HERMES_API Func<std::complex<double> >* init_zero_fn(ElementMode2D mode, int order, Quad2D* quad_2d, int nc);
789 
790  template HERMES_API Func<double>* init_fn(UExtFunction<double>* fu, Func<double>** ext, Func<double>** u_ext, const int order, Geom<double>* geometry, ElementMode2D mode);
791  template HERMES_API Func<std::complex<double> >* init_fn(UExtFunction<std::complex<double> >* fu, Func<std::complex<double> >** ext, Func<std::complex<double> >** u_ext, const int order, Geom<double>* geometry, ElementMode2D mode);
792 
793  template class HERMES_API DiscontinuousFunc < double > ;
794  template class HERMES_API DiscontinuousFunc < std::complex<double> > ;
795  template class HERMES_API GeomVol < double > ;
796  template class HERMES_API GeomSurf < double > ;
797  template class HERMES_API Geom < double > ;
798  template class HERMES_API InterfaceGeom < Hermes::Ord > ;
799  template class HERMES_API InterfaceGeom < double > ;
800  }
801 }
Element * get_active_element() const
Definition: transformable.h:48
Definition: adapt.h:24
T * dx
First-order partial derivatives.
Definition: forms.h:346
int marker
element marker
Definition: element.h:144
double * get_phys_y(int order)
Definition: refmap.cpp:45
Function operating on previous nonlinear solutions in assembling (u_ext)
int id
element id number
Definition: element.h:112
T * dx_neighbor
First-order partial derivatives.
Definition: forms.h:350
HERMES_API void init_geom_surf_allocated(GeomSurf< double > &geom, RefMap *rm, unsigned char isurf, int marker, const int order, double3 *&tan)
Init element geometry for surface integrals.
Definition: forms.cpp:444
Stores one element of a mesh.
Definition: element.h:107
bool reverse_neighbor_side
True if values from the neighbor have to be retrieved in reverse order.
Definition: forms.h:375
Caches precalculated shape function values.
Definition: precalc.h:32
T y[H2D_MAX_INTEGRATION_POINTS_COUNT]
y-coordinates[in physical domain].
Definition: forms.h:46
T x[H2D_MAX_INTEGRATION_POINTS_COUNT]
x-coordinates[in physical domain].
Definition: forms.h:44
int id
ID number of the element.
Definition: forms.h:58
SpaceType get_space_type() const
Returns type of space.
Definition: precalc.cpp:144
This class represents a function with jump discontinuity on an interface of two elements.
Definition: forms.h:335
int elem_marker
Element marker (for both volumetric and surface forms).
Definition: forms.h:49
Geometry (coordinates, normals, tangents) of either an element or an edge.
Definition: forms.h:40
T get_diam_approximation(unsigned char n)
Element diameter approximation.
double3 * get_tangent(int edge, int order=-1)
Definition: refmap.cpp:52
double get_area(unsigned char n, double *wt)
Element area.
DiscontinuousFunc(Func< T > *fn, bool support_on_neighbor, bool reverse=false)
Definition: forms.cpp:192
Represents a function defined on a mesh.
Definition: mesh_function.h:56
T * val_neighbor
Function values. If T == Hermes::Ord and orders vary with direction, this returns max(h_order...
Definition: forms.h:348
HERMES_API void init_geom_vol_allocated(GeomVol< double > &geom, RefMap *rm, const int order)
Init element geometry for volumetric integrals.
Definition: forms.cpp:425
Quad2D * get_quad_2d() const
Returns the current quadrature points.
Definition: function.cpp:129
void set_quad_order(unsigned short order, unsigned short mask=H2D_FN_DEFAULT)
Definition: function.cpp:59
double * get_phys_x(int order)
Definition: refmap.cpp:38
Func< T > * fn_neighbor
Neighbor element's component.
Definition: forms.h:341
T get_area(unsigned char n, double *wt)
Element area.
bool is_jacobian_const() const
Definition: refmap.h:95
Func< T > * fn_central
Central element's component.
Definition: forms.h:339
HERMES_API Func< double > * init_fn(PrecalcShapeset *fu, RefMap *rm, const int order)
Init the shape function for the evaluation of the volumetric/surface integral (transformation of valu...
Definition: forms.cpp:469
unsigned char get_num_components() const
Returns the number of components of the function being represented by the class.
Definition: function.cpp:162
virtual const Scalar * get_dx_values(int component=0) const
Returns the x partial derivative.
Definition: function.cpp:175
virtual const Scalar * get_dy_values(int component=0) const
Returns the y partial derivative.
Definition: function.cpp:182
unsigned char isurf
Internal number of an edge of the element.
Definition: forms.h:159
T * val
Function values. If T == Hermes::Ord and orders vary with direction, this returns max(h_order...
Definition: forms.h:344
int edge_marker
Edge marker.
Definition: forms.h:80
HERMES_API Func< Scalar > * preallocate_fn(pj_pool_t *memoryPool=nullptr)
Preallocate the Func (all we need is np & nc).
Definition: forms.cpp:489
unsigned char isurf
Internal number of an edge of the element.
Definition: forms.h:77
HERMES_API GeomSurf< double > * init_geom_surf(RefMap *rm, unsigned char isurf, int marker, const int order, double3 *&tan)
Init element geometry for surface integrals.
Definition: forms.cpp:437
HERMES_API void init_fn_preallocated(Func< double > *u, PrecalcShapeset *fu, RefMap *rm, const int order)
Init the shape function for the evaluation of the volumetric/surface integral (transformation of valu...
Definition: forms.cpp:497
int np
Number of integration points used by this intance.
Definition: forms.h:248
int elem_marker
Element marker (for both volumetric and surface forms).
Definition: forms.h:149
int edge_marker
Edge marker.
Definition: forms.h:151
HERMES_API GeomVol< double > * init_geom_vol(RefMap *rm, const int order)
Init element geometry for volumetric integrals.
Definition: forms.cpp:418
SolutionType get_type() const
Returns solution type.
Definition: solution.h:143
Calculated function values (from the class Function) on an element for assembling.
Definition: forms.h:214
Represents the reference mapping.
Definition: refmap.h:40
Quad2D * get_quad_2d() const
Returns the current quadrature points.
Definition: refmap.cpp:33
double2x2 * get_inv_ref_map(int order)
Definition: refmap.h:134
MeshSharedPtr get_mesh() const
Return the mesh.
int nc
Number of components. Currently accepted values are 1 (H1, L2 space) and 2 (Hcurl, Hdiv space).
Definition: forms.h:250
HERMES_API Func< Scalar > * init_zero_fn(ElementMode2D mode, int order, Quad2D *quad_2d=nullptr, int nc=1)
Definition: forms.cpp:733
virtual const Scalar * get_fn_values(int component=0) const
Returns function values.
Definition: function.cpp:168
double2x2 * get_const_inv_ref_map()
Definition: refmap.h:115
Represents the solution of a PDE.
Definition: api2d.h:35
virtual void value(int n, Func< Scalar > **ext, Func< Scalar > **u_ext, Func< Scalar > *result, Geom< double > *geometry) const =0
Function returning the value.
T get_diam_approximation(unsigned char n)
Element diameter approximation.