21 template<
typename Scalar>
22 H1Space<Scalar>::H1Space() : Space<Scalar>()
26 template<
typename Scalar>
32 this->own_shapeset =
true;
35 this->precalculate_projection_matrix(2, this->proj_mat, this->chol_p);
39 throw Hermes::Exceptions::Exception(
"P_INIT must be >= 1 in an H1 space.");
41 else this->set_uniform_order_internal(p_init, HERMES_ANY_INT);
47 template<
typename Scalar>
49 :
Space<Scalar>(mesh, shapeset, essential_bcs)
51 init(shapeset, p_init);
54 template<
typename Scalar>
55 H1Space<Scalar>::H1Space(
const Mesh* mesh,
int p_init, Shapeset* shapeset)
56 : Space<Scalar>(mesh, shapeset, NULL)
58 init(shapeset, p_init);
61 template<
typename Scalar>
62 H1Space<Scalar>::~H1Space()
64 if(this->own_shapeset)
65 delete this->shapeset;
68 template<
typename Scalar>
73 this->precalculate_projection_matrix(2, this->proj_mat, this->chol_p);
78 template<
typename Scalar>
81 if(shapeset->
get_id() < 10)
83 this->shapeset = shapeset;
84 this->own_shapeset =
false;
87 throw Hermes::Exceptions::Exception(
"Wrong shapeset type in H1Space<Scalar>::set_shapeset()");
90 template<
typename Scalar>
103 this->vertex_functions_count = 0;
104 for_all_active_elements(e, this->mesh)
106 int order = this->get_element_order(e->
id);
109 for (
unsigned int i = 0; i < e->get_nvert(); i++)
115 if(nd->
n == 0 || is_fixed_vertex(vn->
id))
117 nd->dof = this->H2D_CONSTRAINED_DOF;
121 nd->dof = this->next_dof;
122 this->next_dof += this->stride;
123 this->vertex_functions_count++;
132 template<
typename Scalar>
133 void H1Space<Scalar>::assign_edge_dofs()
137 this->edge_functions_count = 0;
138 for_all_active_elements(e, this->mesh)
140 int order = this->get_element_order(e->id);
143 for (
unsigned int i = 0; i < e->get_nvert(); i++)
146 typename Space<Scalar>::NodeData* nd = this->ndata + vn->id;
148 nd = this->ndata + en->id;
149 if(nd->dof == this->H2D_UNASSIGNED_DOF)
152 if(en->ref > 1 || en->bnd || this->mesh->peek_vertex_node(en->p1, en->p2) != NULL)
154 int ndofs = this->get_edge_order_internal(en) - 1;
158 if(this->essential_bcs != NULL)
159 if(this->essential_bcs->get_boundary_condition(this->mesh->boundary_markers_conversion.get_user_marker(e->en[i]->marker).marker) != NULL)
160 nd->dof = this->H2D_CONSTRAINED_DOF;
163 nd->dof = this->next_dof;
164 this->next_dof += ndofs * this->stride;
165 this->edge_functions_count += ndofs;
169 nd->dof = this->next_dof;
170 this->next_dof += ndofs * this->stride;
171 this->edge_functions_count += ndofs;
175 nd->dof = this->next_dof;
176 this->next_dof += ndofs * this->stride;
177 this->edge_functions_count += ndofs;
188 template<
typename Scalar>
189 void H1Space<Scalar>::assign_bubble_dofs()
193 this->bubble_functions_count = 0;
194 for_all_active_elements(e, this->mesh)
196 int order = this->get_element_order(e->id);
199 typename Space<Scalar>::ElementData* ed = &this->edata[e->id];
200 ed->bdof = this->next_dof;
201 ed->n = order ? this->shapeset->get_num_bubbles(ed->order, e->get_mode()) : 0;
202 this->next_dof += ed->n * this->stride;
203 this->bubble_functions_count += ed->n;
208 template<
typename Scalar>
209 void H1Space<Scalar>::get_vertex_assembly_list(Element* e,
int iv, AsmList<Scalar>* al)
const
211 Node* vn = e->vn[iv];
212 typename Space<Scalar>::NodeData* nd = &this->ndata[vn->id];
213 int index = this->shapeset->get_vertex_index(iv, e->get_mode());
214 if(this->get_element_order(e->id) == 0)
return;
216 if(!vn->is_constrained_vertex())
218 al->add_triplet(index, nd->dof, (nd->dof >= 0) ? 1.0 : *(nd->vertex_bc_coef));
223 for (
int j = 0; j < nd->ncomponents; j++)
224 if(nd->baselist[j].coef != (Scalar) 0)
226 al->add_triplet(index, nd->baselist[j].dof, nd->baselist[j].coef);
231 template<
typename Scalar>
232 void H1Space<Scalar>::get_boundary_assembly_list_internal(Element* e,
int surf_num, AsmList<Scalar>* al)
const
234 Node* en = e->en[surf_num];
235 typename Space<Scalar>::NodeData* nd = &this->ndata[en->id];
236 if(this->get_element_order(e->id) == 0)
243 int ori = (e->vn[surf_num]->id < e->vn[e->next_vert(surf_num)]->id) ? 0 : 1;
244 for (
int j = 0, dof = nd->dof; j < nd->n; j++, dof += this->stride)
245 al->add_triplet(this->shapeset->get_edge_index(surf_num, ori, j + 2, e->get_mode()), dof, 1.0);
249 for (
int j = 0; j < nd->n; j++)
251 al->add_triplet(this->shapeset->get_edge_index(surf_num, 0, j + 2, e->get_mode()), -1, nd->edge_bc_proj[j + 2]);
258 int ori = part < 0 ? 1 : 0;
259 if(part < 0) part ^= ~0;
261 nd = &this->ndata[nd->base->id];
262 for (
int j = 0, dof = nd->dof; j < nd->n; j++, dof += this->stride)
263 al->add_triplet(this->shapeset->get_constrained_edge_index(surf_num, j + 2, ori, part, e->get_mode()), dof, 1.0);
267 template<
typename Scalar>
268 Scalar* H1Space<Scalar>::get_bc_projection(SurfPos* surf_pos,
int order, EssentialBoundaryCondition<Scalar> *bc)
271 Scalar* proj =
new Scalar[order + 1];
273 if(bc->get_value_type() == EssentialBoundaryCondition<Scalar>::BC_CONST)
275 proj[0] = proj[1] = bc->value_const;
277 else if(bc->get_value_type() == EssentialBoundaryCondition<Scalar>::BC_FUNCTION)
279 surf_pos->t = surf_pos->lo;
281 double x, y, n_x, n_y, t_x, t_y;
282 Nurbs* nurbs = surf_pos->base->is_curved() ? surf_pos->base->cm->nurbs[surf_pos->surf_num] : NULL;
283 CurvMap::nurbs_edge(surf_pos->base, nurbs, surf_pos->surf_num, 2.0*surf_pos->t - 1.0, x, y, n_x, n_y, t_x, t_y);
285 proj[0] = bc->value(x, y, n_x, n_y, t_x, t_y);
286 surf_pos->t = surf_pos->hi;
288 CurvMap::nurbs_edge(surf_pos->base, nurbs, surf_pos->surf_num, 2.0*surf_pos->t - 1.0, x, y, n_x, n_y, t_x, t_y);
290 proj[1] = bc->value(x, y, n_x, n_y, t_x, t_y);
296 Scalar* rhs = proj + 2;
297 int mo = quad1d.get_max_order();
298 double2* pt = quad1d.get_points(mo);
301 for (
int i = 0; i < order; i++)
304 int ii = this->shapeset->get_edge_index(0, 0, i + 2, surf_pos->base->get_mode());
305 for (
int j = 0; j < quad1d.get_num_points(mo); j++)
307 double t = (pt[j][0] + 1) * 0.5, s = 1.0 - t;
308 Scalar l = proj[0] * s + proj[1] * t;
309 surf_pos->t = surf_pos->lo * s + surf_pos->hi * t;
311 if(bc->get_value_type() == EssentialBoundaryCondition<Scalar>::BC_CONST)
312 rhs[i] += pt[j][1] * this->shapeset->get_fn_value(ii, pt[j][0], -1.0, 0, surf_pos->base->get_mode())
313 * (bc->value_const - l);
315 else if(bc->get_value_type() == EssentialBoundaryCondition<Scalar>::BC_FUNCTION)
318 double x, y, n_x, n_y, t_x, t_y;
319 Nurbs* nurbs = surf_pos->base->is_curved() ? surf_pos->base->cm->nurbs[surf_pos->surf_num] : NULL;
320 CurvMap::nurbs_edge(surf_pos->base, nurbs, surf_pos->surf_num, 2.0*surf_pos->t - 1.0, x, y, n_x, n_y, t_x, t_y);
322 rhs[i] += pt[j][1] * this->shapeset->get_fn_value(ii, pt[j][0], -1.0, 0, surf_pos->base->get_mode())
323 * (bc->value(x, y, n_x, n_y, t_x, t_y) - l);
329 cholsl(this->proj_mat, order, this->chol_p, rhs, rhs);
335 template<
typename Scalar>
336 inline void H1Space<Scalar>::output_component(
typename Space<Scalar>::BaseComponent*& current,
typename Space<Scalar>::BaseComponent*& last,
typename Space<Scalar>::BaseComponent* min,
337 Node*& edge,
typename Space<Scalar>::BaseComponent*& edge_dofs)
340 if(last != NULL && last->dof == min->dof)
342 last->coef += min->coef * 0.5;
347 if(edge != NULL && this->ndata[edge->id].dof <= min->dof)
352 if(this->ndata[edge->id].dof != min->dof)
354 current += this->ndata[edge->id].n;
360 current->dof = min->dof;
361 current->coef = min->coef * 0.5;
365 template<
typename Scalar>
366 typename Space<Scalar>::BaseComponent* H1Space<Scalar>::merge_baselists(
typename Space<Scalar>::BaseComponent* l1,
int n1,
typename Space<Scalar>::BaseComponent* l2,
int n2,
367 Node* edge,
typename Space<Scalar>::BaseComponent*& edge_dofs,
int& ncomponents)
370 int max_result = n1 + n2;
371 if(edge != NULL) max_result += this->ndata[edge->id].n;
373 typename Space<Scalar>::BaseComponent* result = (
typename Space<Scalar>::BaseComponent*) malloc(max_result *
sizeof(
typename Space<Scalar>::BaseComponent));
374 typename Space<Scalar>::BaseComponent* current = result;
375 typename Space<Scalar>::BaseComponent* last = NULL;
379 while (i1 < n1 && i2 < n2)
381 if(l1[i1].dof < l2[i2].dof)
382 output_component(current, last, l1 + i1++, edge, edge_dofs);
384 output_component(current, last, l2 + i2++, edge, edge_dofs);
388 while (i1 < n1) output_component(current, last, l1 + i1++, edge, edge_dofs);
389 while (i2 < n2) output_component(current, last, l2 + i2++, edge, edge_dofs);
395 current += this->ndata[edge->id].n;
400 ncomponents = current - result;
401 if(ncomponents < max_result)
403 typename Space<Scalar>::BaseComponent* reallocated_result = (
typename Space<Scalar>::BaseComponent*) realloc(result, ncomponents *
sizeof(
typename Space<Scalar>::BaseComponent));
404 if(edge_dofs != NULL)
406 edge_dofs = reallocated_result + (edge_dofs - result);
408 return reallocated_result;
414 template<
typename Scalar>
415 void H1Space<Scalar>::update_constrained_nodes(Element* e, EdgeInfo* ei0, EdgeInfo* ei1, EdgeInfo* ei2, EdgeInfo* ei3)
418 EdgeInfo* ei[4] = { ei0, ei1, ei2, ei3 };
419 typename Space<Scalar>::NodeData* nd;
421 if(this->get_element_order(e->id) == 0)
return;
426 for (
unsigned int i = 0; i < e->get_nvert(); i++)
430 nd = &this->ndata[e->en[i]->id];
431 nd->base = ei[i]->node;
432 nd->part = ei[i]->part;
433 if(ei[i]->ori) nd->part ^= ~0;
442 for (
unsigned int i = 0; i < e->get_nvert(); i++)
447 Node* mid_vn = this->get_mid_edge_vertex_node(e, i, j);
448 if(mid_vn != NULL && mid_vn->is_constrained_vertex())
450 Node* mid_en = this->mesh->peek_edge_node(e->vn[i]->id, e->vn[j]->id);
454 ei[i]->node = mid_en;
458 ei[i]->ori = (e->vn[i]->id < e->vn[j]->id) ? 0 : 1;
465 for (
unsigned int i = 0; i < e->get_nvert(); i++)
467 if(ei[i] == NULL)
continue;
470 Node* mid_vn = this->get_mid_edge_vertex_node(e, i, j);
471 if(mid_vn == NULL)
continue;
473 Node* vn[2] = { e->vn[i], e->vn[j] };
474 Node* en = ei[i]->node;
475 typename Space<Scalar>::BaseComponent *bl[2], dummy_bl[2];
476 int nc[2] = { 0, 0 };
479 for (k = 0; k < 2; k++)
481 nd = &this->ndata[vn[k]->id];
482 if(vn[k]->is_constrained_vertex())
484 bl[k] = nd->baselist;
485 nc[k] = nd->ncomponents;
489 dummy_bl[k].dof = nd->dof;
490 dummy_bl[k].coef = (nd->dof >= 0) ? 1.0 : *nd->vertex_bc_coef;
491 bl[k] = &dummy_bl[k];
497 typename Space<Scalar>::BaseComponent* edge_dofs;
498 nd = &this->ndata[mid_vn->id];
499 nd->baselist = merge_baselists(bl[0], nc[0], bl[1], nc[1], en, edge_dofs, nd->ncomponents);
500 this->bc_data.push_back(nd->baselist);
503 double mid = (ei[i]->lo + ei[i]->hi) * 0.5;
504 nd = &this->ndata[en->id];
505 for (k = 0; k < nd->n; k++, edge_dofs++)
507 edge_dofs->dof = nd->dof + k*this->stride;
508 edge_dofs->coef = this->shapeset->get_fn_value(this->shapeset->get_edge_index(0, ei[i]->ori, k + 2, e->get_mode()), mid, -1.0, 0, e->get_mode());
515 EdgeInfo half_ei_data[4][2];
516 EdgeInfo* half_ei[4][2];
517 for (
unsigned int i = 0; i < e->get_nvert(); i++)
521 half_ei[i][0] = half_ei[i][1] = NULL;
525 EdgeInfo* h0 = half_ei[i][0] = half_ei_data[i];
526 EdgeInfo* h1 = half_ei[i][1] = half_ei_data[i] + 1;
528 h0->node = h1->node = ei[i]->node;
529 h0->part = (ei[i]->part + 1) * 2;
530 h1->part = h0->part + 1;
531 h0->hi = h1->lo = (ei[i]->lo + ei[i]->hi) / 2;
534 h1->ori = h0->ori = ei[i]->ori;
541 update_constrained_nodes(e->sons[0], half_ei[0][0], NULL, half_ei[2][1], NULL);
542 update_constrained_nodes(e->sons[1], half_ei[0][1], half_ei[1][0], NULL, NULL);
543 update_constrained_nodes(e->sons[2], NULL, half_ei[1][1], half_ei[2][0], NULL);
544 update_constrained_nodes(e->sons[3], NULL, NULL, NULL, NULL);
546 else if(e->sons[2] == NULL)
548 update_constrained_nodes(e->sons[0], ei[0], half_ei[1][0], NULL, half_ei[3][1]);
549 update_constrained_nodes(e->sons[1], NULL, half_ei[1][1], ei[2], half_ei[3][0]);
551 else if(e->sons[0] == NULL)
553 update_constrained_nodes(e->sons[2], half_ei[0][0], NULL, half_ei[2][1], ei[3]);
554 update_constrained_nodes(e->sons[3], half_ei[0][1], ei[1], half_ei[2][0], NULL);
558 update_constrained_nodes(e->sons[0], half_ei[0][0], NULL, NULL, half_ei[3][1]);
559 update_constrained_nodes(e->sons[1], half_ei[0][1], half_ei[1][0], NULL, NULL);
560 update_constrained_nodes(e->sons[2], NULL, half_ei[1][1], half_ei[2][0], NULL);
561 update_constrained_nodes(e->sons[3], NULL, NULL, half_ei[2][1], half_ei[3][0]);
566 template<
typename Scalar>
570 for_all_base_elements(e, this->mesh)
571 update_constrained_nodes(e, NULL, NULL, NULL, NULL);
574 template<
typename Scalar>
578 fixed_vertices.push_back(fv);
581 template<
typename Scalar>
584 for (
unsigned int i = 0; i < fixed_vertices.size(); i++)
585 if(fixed_vertices[i].
id ==
id)
591 template<
typename Scalar>
595 for (
unsigned int i = 0; i < fixed_vertices.size(); i++)
597 Scalar* fixv =
new Scalar[1];
598 *fixv = fixed_vertices[i].value;
600 nd->vertex_bc_coef = fixv;
601 this->bc_data.push_back(fixv);