45 Hermes::Ord d1(order > 1 ? order - 1 : order);
47 this->val = this->val0 = this->val1 = d;
48 this->dx = this->dy = this->curl = this->div = d1;
50 #ifdef H2D_USE_SECOND_DERIVATIVES
51 Hermes::Ord d2(std::min(0, order - 2));
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);
61 throw Hermes::Exceptions::Exception(
"Unable to subtract a function due to a different number of components (this: %d, other: %d)", nc, func->
nc);
63 subtract(this->val, func->val);
64 subtract(this->dx, func->dx);
65 subtract(this->dy, func->dy);
67 #ifdef H2D_USE_SECOND_DERIVATIVES
68 subtract(this->laplace, func->laplace);
73 subtract(this->val0, func->val0);
74 subtract(this->val1, func->val1);
75 subtract(this->curl, func->curl);
76 subtract(this->div, func->div);
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);
85 throw Hermes::Exceptions::Exception(
"Unable to subtract a function due to a different number of components (this: %d, other: %d)", nc, func->nc);
87 subtract(this->val, func->val);
88 subtract(this->dx, func->dx);
89 subtract(this->dy, func->dy);
91 #ifdef H2D_USE_SECOND_DERIVATIVES
92 subtract(this->laplace, func->laplace);
97 subtract(this->val0, func->val0);
98 subtract(this->val1, func->val1);
99 subtract(this->curl, func->curl);
100 subtract(this->div, func->div);
106 if (attribute !=
nullptr && other_attribute !=
nullptr)
108 for (
int i = 0; i < this->np; i++)
109 attribute[i] -= other_attribute[i];
115 if (attribute !=
nullptr && other_attribute !=
nullptr)
117 for (
int i = 0; i < this->np; i++)
118 attribute[i] -= other_attribute[i];
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);
127 throw Hermes::Exceptions::Exception(
"Unable to add a function due to a different number of components (this: %d, other: %d)", nc, func->
nc);
129 add(this->val, func->val);
130 add(this->dx, func->dx);
131 add(this->dy, func->dy);
133 #ifdef H2D_USE_SECOND_DERIVATIVES
134 add(this->laplace, func->laplace);
139 add(this->val0, func->val0);
140 add(this->val1, func->val1);
141 add(this->curl, func->curl);
142 add(this->div, func->div);
146 #ifdef H2D_USE_SECOND_DERIVATIVES
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);
154 throw Hermes::Exceptions::Exception(
"Unable to add a function due to a different number of components (this: %d, other: %d)", nc, func->nc);
156 add(this->val, func->val);
157 add(this->dx, func->dx);
158 add(this->dy, func->dy);
160 #ifdef H2D_USE_SECOND_DERIVATIVES
161 add(this->laplace, func->laplace);
166 add(this->val0, func->val0);
167 add(this->val1, func->val1);
168 add(this->curl, func->curl);
169 add(this->div, func->div);
175 if (attribute !=
nullptr && other_attribute !=
nullptr)
177 for (
int i = 0; i < this->np; i++)
178 attribute[i] += other_attribute[i];
184 if (attribute !=
nullptr && other_attribute !=
nullptr)
186 for (
int i = 0; i < this->np; i++)
187 attribute[i] += other_attribute[i];
193 Func<T>(fn->np, fn->nc), fn_central(nullptr), fn_neighbor(nullptr), reverse_neighbor_side(reverse)
196 throw Hermes::Exceptions::Exception(
"Invalid arguments to DiscontinuousFunc constructor.");
197 if (support_on_neighbor)
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++)
208 this->dx_neighbor[i] = fn->dx[this->np - i - 1];
209 this->dy_neighbor[i] = fn->dy[this->np - i - 1];
216 this->dy_neighbor = fn->dy;
219 this->
val = this->
dx = this->dy =
nullptr;
233 Func<T>(fn_c->np, fn_c->nc), fn_central(fn_c), fn_neighbor(fn_n), reverse_neighbor_side(reverse)
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++)
243 this->dx_neighbor[i] =
fn_neighbor->dx[this->np - i - 1];
244 this->dy_neighbor[i] =
fn_neighbor->dy[this->np - i - 1];
259 fn_central(nullptr), fn_neighbor(nullptr), reverse_neighbor_side(reverse)
262 throw Hermes::Exceptions::Exception(
"Invalid arguments to DiscontinuousFunc constructor.");
263 if (support_on_neighbor)
268 this->dy_neighbor = fn->dy;
280 fn_central(fn_c), fn_neighbor(fn_n), reverse_neighbor_side(reverse)
294 if (fn_central !=
nullptr && func.
fn_central !=
nullptr)
296 if (fn_neighbor !=
nullptr && func.
fn_neighbor !=
nullptr)
299 if (reverse_neighbor_side)
309 DiscontinuousFunc<T>::~DiscontinuousFunc()
315 void DiscontinuousFunc<T>::free()
317 if (fn_central !=
nullptr)
320 fn_central =
nullptr;
322 if (fn_neighbor !=
nullptr)
324 if (reverse_neighbor_side)
326 free_with_check(this->val_neighbor);
327 free_with_check(this->dx_neighbor);
328 free_with_check(this->dy_neighbor);
331 fn_neighbor =
nullptr;
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();
343 for (
unsigned char i = 0; i < n; i++)
345 if (this->x[i] < x_min)
347 if (this->x[i] > x_max)
350 if (this->y[i] < y_min)
352 if (this->y[i] > y_max)
356 return std::sqrt((x_max - x_min) * (x_max - x_min) + (y_max - y_min) * (y_max - y_min));
363 for (
unsigned char i = 0; i < n; i++)
382 this->wrapped_geom = geom;
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();
393 for (
unsigned char i = 0; i < n; i++)
395 if (this->x[i] < x_min)
397 if (this->x[i] > x_max)
400 if (this->y[i] < y_min)
402 if (this->y[i] > y_max)
406 return std::sqrt((x_max - x_min) * (x_max - x_min) + (y_max - y_min) * (y_max - y_min));
413 for (
unsigned char i = 0; i < n; i++)
429 geom.
id = element->
id;
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));
456 unsigned char np = quad->get_num_points(order, mode);
458 memcpy(geom.
x, rm->
get_phys_x(order), np *
sizeof(double));
459 memcpy(geom.
y, rm->
get_phys_y(order), np *
sizeof(double));
461 for (
int i = 0; i < np; i++)
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];
478 template<
typename Scalar>
488 template<
typename Scalar>
501 #ifdef H2D_USE_SECOND_DERIVATIVES
502 if (space_type == HERMES_H1_SPACE || space_type == HERMES_L2_SPACE)
516 if (space_type == HERMES_H1_SPACE || space_type == HERMES_L2_SPACE)
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();
534 for (
int i = 0; i < np; 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);
540 #ifdef H2D_USE_SECOND_DERIVATIVES
542 mm = rm->get_second_ref_map(order);
543 for (
int i = 0; i < np; i++, mm++)
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);
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);
562 #ifdef H2D_USE_SECOND_DERIVATIVES
564 mm = rm->get_second_ref_map(order);
565 for (
int i = 0; i < np; i++, m++, mm++)
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]);
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);
579 for (
int i = 0; i < np; i++, m++)
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]);
589 else if (space_type == HERMES_HCURL_SPACE)
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++)
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]);
612 for (
int i = 0; i < np; i++, m++)
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]);
621 else if (space_type == HERMES_HDIV_SPACE)
633 double determinant = (const_inv_ref_map00 * const_inv_ref_map11 - const_inv_ref_map10 * const_inv_ref_map01);
635 for (
int i = 0; i < np; i++)
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]);
645 for (
int i = 0; i < np; i++, m++)
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]);
654 throw Hermes::Exceptions::Exception(
"Wrong space type - space has to be either H1, Hcurl, Hdiv or L2");
657 template<
typename Scalar>
662 throw Hermes::Exceptions::Exception(
"nullptr MeshFunction in Func<Scalar>*::init_fn().");
664 throw Hermes::Exceptions::Exception(
"Uninitialized MeshFunction used.");
667 #ifdef H2D_USE_SECOND_DERIVATIVES
671 if ((sln->get_space_type() == HERMES_H1_SPACE || sln->get_space_type() == HERMES_L2_SPACE) && sln->
get_type() != HERMES_EXACT)
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)
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];
709 for (
int i = 0; i < np; i++)
710 u->curl[i] = dx1[i] - dy0[i];
714 for (
int i = 0; i < np; i++)
715 u->div[i] = dx0[i] + dy1[i];
719 template<
typename Scalar>
724 throw Hermes::Exceptions::Exception(
"nullptr UExtFunction in Func<Scalar>*::init_fn().");
726 Quad2D* quad = &g_quad_2d_std;
727 unsigned char np = quad->get_num_points(order, mode);
729 fu->
value(np, ext, u_ext, u, geometry);
732 template<
typename Scalar>
736 quad = &g_quad_2d_std;
738 unsigned char np = quad->get_num_points(order, mode);
743 memset(u->val, 0, np *
sizeof(Scalar));
744 memset(u->dx, 0, np *
sizeof(Scalar));
745 memset(u->dy, 0, np *
sizeof(Scalar));
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));
757 template<
typename Scalar>
761 Quad2D* quad = &g_quad_2d_std;
763 unsigned char np = quad->get_num_points(order, mode);
768 throw Hermes::Exceptions::Exception(
"nullptr UExtFunction in Func<Scalar>*::init_fn().");
770 fu->
value(np, ext, u_ext, u, geometry);
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);
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);
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);
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);
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);
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 > ;
T * dx
First-order partial derivatives.
double * get_phys_y(int order)
Function operating on previous nonlinear solutions in assembling (u_ext)
T * dx_neighbor
First-order partial derivatives.
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.
Stores one element of a mesh.
bool reverse_neighbor_side
True if values from the neighbor have to be retrieved in reverse order.
Caches precalculated shape function values.
T y[H2D_MAX_INTEGRATION_POINTS_COUNT]
y-coordinates[in physical domain].
T x[H2D_MAX_INTEGRATION_POINTS_COUNT]
x-coordinates[in physical domain].
int id
ID number of the element.
SpaceType get_space_type() const
Returns type of space.
This class represents a function with jump discontinuity on an interface of two elements.
int elem_marker
Element marker (for both volumetric and surface forms).
Geometry (coordinates, normals, tangents) of either an element or an edge.
T get_diam_approximation(unsigned char n)
Element diameter approximation.
double3 * get_tangent(int edge, int order=-1)
double get_area(unsigned char n, double *wt)
Element area.
DiscontinuousFunc(Func< T > *fn, bool support_on_neighbor, bool reverse=false)
Represents a function defined on a mesh.
T * val_neighbor
Function values. If T == Hermes::Ord and orders vary with direction, this returns max(h_order...
HERMES_API void init_geom_vol_allocated(GeomVol< double > &geom, RefMap *rm, const int order)
Init element geometry for volumetric integrals.
Quad2D * get_quad_2d() const
Returns the current quadrature points.
void set_quad_order(unsigned short order, unsigned short mask=H2D_FN_DEFAULT)
double * get_phys_x(int order)
Func< T > * fn_neighbor
Neighbor element's component.
T get_area(unsigned char n, double *wt)
Element area.
bool is_jacobian_const() const
Func< T > * fn_central
Central element's component.
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...
unsigned char get_num_components() const
Returns the number of components of the function being represented by the class.
virtual const Scalar * get_dx_values(int component=0) const
Returns the x partial derivative.
virtual const Scalar * get_dy_values(int component=0) const
Returns the y partial derivative.
unsigned char isurf
Internal number of an edge of the element.
T * val
Function values. If T == Hermes::Ord and orders vary with direction, this returns max(h_order...
int edge_marker
Edge marker.
HERMES_API Func< Scalar > * preallocate_fn(pj_pool_t *memoryPool=nullptr)
Preallocate the Func (all we need is np & nc).
unsigned char isurf
Internal number of an edge of the element.
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.
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...
int np
Number of integration points used by this intance.
int elem_marker
Element marker (for both volumetric and surface forms).
int edge_marker
Edge marker.
HERMES_API GeomVol< double > * init_geom_vol(RefMap *rm, const int order)
Init element geometry for volumetric integrals.
SolutionType get_type() const
Returns solution type.
Calculated function values (from the class Function) on an element for assembling.
Represents the reference mapping.
Quad2D * get_quad_2d() const
Returns the current quadrature points.
double2x2 * get_inv_ref_map(int order)
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).
HERMES_API Func< Scalar > * init_zero_fn(ElementMode2D mode, int order, Quad2D *quad_2d=nullptr, int nc=1)
virtual const Scalar * get_fn_values(int component=0) const
Returns function values.
double2x2 * get_const_inv_ref_map()
Represents the solution of a PDE.
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.