Plugins
Loading...
Searching...
No Matches
fract_dimadapt_impl.h
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2025 Gesellschaft fuer Anlagen- und Reaktorsicherheit gGmbH
3 * SPDX-License-Identifier: EUPL-1.2
4 * SPDX-FileContributor: Sabine Stichel
5 * SPDX-FileContributor: Goethe Universität Frankfurt
6 * SPDX-FileType: SOURCE
7 *
8 * This file is part of d3f++.
9 * d3f++ is an extension for UG4. Licensing information and citation requirements of UG4 are provided in LICENSES/UG4-LGPL_2.1
10 */
11
12
13/*
14 * Implementation of the dimension-adaptive fracture representation
15 */
16
17// ug4 headers
20#include "lib_grid/lg_base.h"
21
22// Only required for debug saves
24
25namespace ug {
26namespace d3f {
27
34template <typename TDomain,typename TAlgebra>
36(
38 const char* ss_name,
39 const std::vector<number> normal,
40 number aperture,
41 bool shift
42)
43{
44// Check the domain:
45 if (domain.invalid ())
46 UG_THROW ("FractDimadapt: Invalid domain specified!");
47
48 m_dom = domain;
49
50 m_shift = shift;
51
52// Initialize the data:
53 m_spSH = domain->subset_handler ();
54 m_fractSsGrp.set_subset_handler (m_spSH);
55
56//initialize
57 m_FirstFullLevel = -1;
58 m_FractureIsFullDimensional = -1;
59 m_density_type = "NONE";
60 m_viscosity_type = "NONE";
61 m_permeability_f = 0.0;
62 m_permeability_m = 0.0;
63//set default gravity
64 m_Gravity[0] = 0.0;
65 m_Gravity[1] = 0.0;
66 m_Gravity[dim-1] = -9.81;
67
68// Initialize the attachment:
69 MultiGrid * pMG = (MultiGrid *) (m_spSH->multi_grid ());
70 pMG->template attach_to_dv<Vertex> (m_aVertexAuxMarks, F_NONE);
71 m_aaVertAuxMarks.access (*pMG, m_aVertexAuxMarks);
72
73 pMG->template attach_to_dv<Edge> (m_aEdgeAuxMarks, F_NONE);
74 m_aaEdgeAuxMarks.access (*pMG, m_aEdgeAuxMarks);
75
76 MathVector<dim> initial;
77 for(int i=0;i<dim;i++)
78 initial[i]=0.0;
79 pMG->template attach_to_dv<Vertex> (m_aVertexShift, initial);
80 m_aaVertexShift.access (*pMG, m_aVertexShift);
81
82// Register the callbacks in the message hub:
83 m_spGridAdaptionCallbackID =
84 pMG->message_hub()->register_class_callback
86 m_spGridDistributionCallbackID =
87 pMG->message_hub()->register_class_callback
89
90 // Add the subsets to the group:
91 m_fractSsGrp.add (ss_name);
92 for (int d=0;d < dim;d++)
93 m_fractNormal[d] = normal[d];
94 m_aperture = aperture;
95
96 // Mark the vertices:
97 mark_vertices ();
98}
99
103template <typename TDomain,typename TAlgebra>
105{
106 MultiGrid * pMG = (MultiGrid *) (m_spSH->multi_grid ());
107 m_aaVertAuxMarks.invalidate ();
108 pMG->template detach_from<Vertex> (m_aVertexAuxMarks);
109 m_aaEdgeAuxMarks.invalidate ();
110 pMG->template detach_from<side_type> (m_aEdgeAuxMarks);
111}
112
113
117template <typename TDomain,typename TAlgebra>
119(
120 const GridMessage_Adaption & msg
121)
122{
123 if (msg.adaption_ends ())
124 mark_vertices ();
125}
126
130template <typename TDomain,typename TAlgebra>
132(
133 const GridMessage_Distribution & msg
134)
135{
136 if (msg.msg () == GMDT_DISTRIBUTION_STOPS)
137 mark_vertices ();
138}
139
143template <typename TDomain,typename TAlgebra>
145{
146 typedef typename geometry_traits<element_type>::const_iterator t_elem_iter;
147
148 MultiGrid * pMG = (MultiGrid *) (m_spSH->multi_grid ());
149 m_NumberLevels = pMG->num_levels ();
150 if(m_NumberLevels==(int)max_number_levels)
151 UG_THROW ("FractDimadapt: Not enough Levels allocated!");
152
154 typename Grid::traits<Edge>::secure_container edge_list;
155
157 const position_accessor_type& posAcc = m_dom->position_accessor();
158
159 number eps = 1E-10;
160
161 UG_LOG("mark vertices\n");
162
163
164 for (int lev = 0; lev < m_NumberLevels; lev++)
165 {
166 //First find nodes on fracture mean plane
167 //To this end. Mark Fracture Vertices with F_INNER
168 for (size_t i = 0; i < m_fractSsGrp.size (); i++)
169 {
170 int si = m_fractSsGrp [i];
171
172 t_elem_iter list_end = m_spSH->template end<element_type> (si, lev);
173 for (t_elem_iter iElem = m_spSH->template begin<element_type> (si, lev);
174 iElem != list_end; ++iElem)
175 {
176 element_type * elem = *iElem;
177 for (size_t j = 0; j < elem->num_vertices (); j++)
178 {
179 Vertex * vert = elem->vertex(j);
180 m_aaVertAuxMarks [vert] = (! vert->is_constrained ())? F_INNER : F_OUTER;
181 // REMARK: Constrained vertices cannot be inner for fractures!
182 // We cannot catch this situation somewhere else, so we do it here.
183 }
184 }
185 }
186
187 // Unmark all vertices in the bulk medium elements:
188 SubsetGroup bulkSsGrp (m_spSH);
189 for (int si = 0; si < m_spSH->num_subsets (); si++)
190 if (DimensionOfSubset (*m_spSH, si) == dim && ! m_fractSsGrp.contains (si))
191 {
192 t_elem_iter list_end = m_spSH->template end<element_type> (si, lev);
193 for (t_elem_iter iElem = m_spSH->template begin<element_type> (si, lev);
194 iElem != list_end; ++iElem)
195 {
196 element_type * elem = *iElem;
197 for (size_t i = 0; i < elem->num_vertices (); i++)
198 m_aaVertAuxMarks [elem->vertex(i)] = F_OUTER;
199 }
200 }
201 }
202
203 //Then add marked nodes to list
204 //First find inner nodes on level 0 (on lev 0 all inner are mid)
205 NumberFractNodes[0] = 0.0;
206 for (size_t i = 0; i < m_fractSsGrp.size (); i++)
207 {
208 int si = m_fractSsGrp [i];
209 t_elem_iter list_end = m_spSH->template end<element_type> (si, 0);
210 for (t_elem_iter iElem = m_spSH->template begin<element_type> (si, 0);
211 iElem != list_end; ++iElem)
212 {
213 element_type * elem = *iElem;
214 for (size_t j = 0; j < elem->num_vertices (); j++)
215 {
216 Vertex * vert = elem->vertex(j);
217 int mark = m_aaVertAuxMarks [vert];
218 if(mark == F_INNER)
219 {
220 FractNode[0][NumberFractNodes[0]][0] = vert;
221 NumberFractNodes[0]++;
222 if(NumberFractNodes[0]==(int)max_number_fracture_midnodes)
223 UG_THROW ("FractDimadapt: Not enough Fracture nodes allocated!");
224 m_aaVertAuxMarks [vert] = F_MID; //to avoid double counting
225 }
226 }
227 }
228 }
229 //then on other levels find inner nodes that lie on fracture mean plane
230 //given by line through mid with normal
231 number c = VecDot(posAcc[FractNode[0][0][0]],m_fractNormal);
232 for (int lev = 1; lev < m_NumberLevels; lev++)
233 {
234 NumberFractNodes[lev] = 0.0;
235 for (size_t i = 0; i < m_fractSsGrp.size (); i++)
236 {
237 int si = m_fractSsGrp [i];
238 t_elem_iter list_end = m_spSH->template end<element_type> (si, lev);
239 for (t_elem_iter iElem = m_spSH->template begin<element_type> (si, lev);
240 iElem != list_end; ++iElem)
241 {
242 element_type * elem = *iElem;
243 for (size_t j = 0; j < elem->num_vertices (); j++)
244 {
245 Vertex * vert = elem->vertex(j);
246 int mark = m_aaVertAuxMarks [vert];
247 if(mark == F_INNER)
248 {
249 number c_a = VecDot(posAcc[vert],m_fractNormal);
250 if(fabs(c-c_a)<eps)
251 {
252 FractNode[lev][NumberFractNodes[lev]][0] = vert;
253 NumberFractVertNodes[lev][NumberFractNodes[lev]] = 0.0;
254 NumberFractNodes[lev]++;
255 if(NumberFractNodes[lev]==(int)max_number_fracture_midnodes)
256 UG_THROW ("FractDimadapt: Not enough Fracture nodes allocated!");
257 m_aaVertAuxMarks [vert] = F_MID; //to avoid double counting
258 }
259 }
260 }
261 }
262 }
263 }
264
265 //now find corresponding nodes along the line given by normal
266 //(normal to the fracture is parallel to this line)
267 MathVector<dim> tangential;
268 tangential[0]= m_fractNormal[1];
269 tangential[1]= -m_fractNormal[0];
270 //todo: 3d tangential berechnen!!
271 for (int lev = 0; lev < m_NumberLevels; lev++)
272 {
273 int TriangleCount = 0;
274 std::vector<int> bnd_count(NumberFractNodes[lev]);
275 for (int k = 0; k < NumberFractNodes[lev]; k++)
276 bnd_count[k] = 0;
277 for (size_t i = 0; i < m_fractSsGrp.size (); i++)
278 {
279 int si = m_fractSsGrp [i];
280 t_elem_iter list_end = m_spSH->template end<element_type> (si, lev);
281 for (t_elem_iter iElem = m_spSH->template begin<element_type> (si, lev);
282 iElem != list_end; ++iElem)
283 {
284 element_type * elem = *iElem;
285 for (size_t j = 0; j < elem->num_vertices (); j++)
286 {
287 Vertex * vert = elem->vertex(j);
288 int mark = m_aaVertAuxMarks [vert];
289 if(mark == F_MID || mark == F_BND || mark == F_VERT)
290 continue;
291 if(mark == F_NONE)
292 UG_THROW ("FractDimadapt:Fracture marks not set correctly!");
293 //UG_LOG("\t teste " << posAcc[vert]<<" "<<mark<<"\n");
294 number c_a = VecDot(posAcc[vert],tangential);
295 number c_b;
296 int corner = 1;
297 for (int k = 0; k < NumberFractNodes[lev]; k++)
298 {
299 Vertex * midvert = FractNode[lev][k][0];
300 //UG_LOG("\t mid " << posAcc[midvert]<<"\n");
301 c_b = VecDot(posAcc[midvert],tangential);
302 if(fabs(c_b-c_a)<eps)
303 {
304 if(mark == F_OUTER)
305 {
306 //UG_LOG("\t OUTER "<<"\n");
307 FractNode[lev][k][bnd_count[k]+1] = vert;
308 bnd_count[k]++;
309 m_aaVertAuxMarks [vert] = F_BND; //to avoid double counting
310 k=NumberFractNodes[lev];
311 }
312 else if(mark == F_INNER)
313 {
314 //UG_LOG("\t INNER "<<"\n");
315 FractNode[lev][k][3+NumberFractVertNodes[lev][k]] = vert;
316 NumberFractVertNodes[lev][k]++;
317 if(NumberFractVertNodes[lev][k]== (int)max_number_fracture_layers)
318 UG_THROW ("FractDimadapt: Not enough Fracture vert nodes allocated!");
319 m_FractureIsFullDimensional = 1;
320 m_aaVertAuxMarks [vert] = F_VERT; //to avoid double counting
321 k=NumberFractNodes[lev];
322 if(m_FirstFullLevel < 0)
323 {
324 m_FirstFullLevel = lev;
325 }
326 }
327 else
328 UG_THROW ("FractDimadapt:Fracture marks maybe not set correctly!");
329 corner = 0;
330 }
331 }
332 if(corner == 1)
333 {
334 m_aaVertAuxMarks [vert] = F_CORNER;
335 CornerTriangleList[lev][TriangleCount] = elem;
336 TriangleCount++;
337 //UG_LOG("\t CORNER "<<" "<<posAcc[vert]<<"\n");
338 if(TriangleCount > 4)
339 UG_THROW ("FractDimadapt: Something wrong with corner triangle identification"<<TriangleCount);
340
341 }
342 }
343 }
344// if(TriangleCount != 4) //only for full dim
345// UG_THROW ("FractDimadapt: Something wrong with corner triangle identification"<<TriangleCount);
346 }
347
348 int deg_count = 0; //for degenerated quadrilaterals that are triangles in full dim
349 for (int k = 0; k < NumberFractNodes[lev]; k++)
350 {
351 if(bnd_count[k]!=2)
352 {
353 if(m_shift == true)
354 {
355 if(bnd_count[k]==1) //degenerated end quadri sets corner node as bnd node to triquadnode
356 {
357 deg_count++;
358 FractNode[lev][k][1] = NULL;
359 FractNode[lev][k][2] = NULL;
360 }
361 //else //in debug case possible
362 // UG_THROW ("FractDimadapt: Wrong number fract boundary nodes!"<<bnd_count[k]<<" "<<posAcc[FractNode[lev][k][0]]);
363 }
364 else
365 {
366 if(bnd_count[k]==0) //degenerated end quadri without shift: quadtrinode has no bnd nodes
367 deg_count++;
368 else
369 UG_THROW ("FractDimadapt: Wrong number fract boundary nodes!"<<bnd_count[k]);
370 }
371 }
372 }
373 if(deg_count!=0 && deg_count!=2)
374 UG_THROW ("FractDimadapt: Wrong number fract boundary nodes (degcount)!");
375 }
376
377 //set FractureIsFullDimensional also for cases without F_VERT nodes in fracture
378 //i.e. for full-dim fractures with only 2 layers
379 //check only if FractureIsFullDimensional is not set before
380 if(m_FractureIsFullDimensional < 0)
381 {
382 //check shift on toplevel
383 int lev = m_NumberLevels-1;
384 //check only for one point
385 int k = 1;
386 MathVector<dim> coords_1,coords_2,shift;
387 coords_1 = posAcc[FractNode[lev][k][0]];
388 coords_2 = posAcc[FractNode[lev][k][1]];
389 VecSubtract(shift,coords_1,coords_2);
390 if(fabs(VecLength(shift))>1e-6)
391 {
392 m_FractureIsFullDimensional = 1;
393 m_FirstFullLevel = m_NumberLevels;
394 }
395 }
396
397 //set shift of boundary nodes (can only be set for full dim fracture)
398 if(m_FractureIsFullDimensional == 1)
399 {
400 for (int lev = 0; lev < m_NumberLevels; lev++)
401 {
402 for (int k = 0; k < NumberFractNodes[lev]; k++)
403 {
404 MathVector<dim> coords_1,coords_2,shift;
405 coords_1 = posAcc[FractNode[lev][k][0]];
406 coords_2 = posAcc[FractNode[lev][k][1]];
407 VecSubtract(shift,coords_1,coords_2);
408 m_aaVertexShift [FractNode[lev][k][1]] = shift;
409 coords_2 = posAcc[FractNode[lev][k][2]];
410 VecSubtract(shift,coords_1,coords_2);
411 m_aaVertexShift [FractNode[lev][k][2]] = shift;
412 }
413 }
414 }
415
416
417 //print list
418// for (int lev = 0; lev < m_NumberLevels; lev++)
419// {
420// UG_LOG(" level "<<lev<<" "<<NumberFractNodes[lev] <<" \n");
421// for (int k = 0; k < NumberFractNodes[lev]; k++)
422// {
423// UG_LOG("vert nodes "<<NumberFractVertNodes[lev][k]<<"\n ");
424// UG_LOG("\t vert " << posAcc[FractNode[lev][k][0]] <<" "<< posAcc[FractNode[lev][k][1]] <<" "<<posAcc[FractNode[lev][k][2]] );
425// UG_LOG("\t shift " << vert_shift(FractNode[lev][k][1]) <<" "<<vert_shift(FractNode[lev][k][2]) );
426// for (int i = 3; i < NumberFractVertNodes[lev][k]+3; i++)
427// {
428// UG_LOG(" vert " << posAcc[FractNode[lev][k][i]] );
429// }
430// UG_LOG(" \n ");
431// }
432// }
433
434
435 //Mark Fracture Sides
436 for (int lev = 0; lev < m_NumberLevels; lev++)
437 {
438 for (size_t i = 0; i < m_fractSsGrp.size (); i++)
439 {
440 int si = m_fractSsGrp [i];
441 t_elem_iter list_end = m_spSH->template end<element_type> (si, lev);
442 for (t_elem_iter iElem = m_spSH->template begin<element_type> (si, lev);
443 iElem != list_end; ++iElem)
444 {
445 element_type * elem = *iElem;
446
447 //todo 3d faces
448
449 // Loop over the edges: We look for sides with only inner or only outer corners
450 pMG->associated_elements_sorted (edge_list, elem);
451 for (size_t j = 0; j < edge_list.size (); j++)
452 {
453 Edge * edge = edge_list [j];
454 bool has_inner = false, has_outer = false;
455 // bool has_corner = false; // currently unused, silencing warning (avogel)
456 bool has_vert = false;
457 //todo: check corner case in 3d
458 size_t n_co = edge->num_vertices ();
459 for (size_t co = 0; co < n_co; co++)
460 {
461 int mark = vert_mark (edge->vertex (co));
462 if (mark == F_BND)
463 has_outer = true;
464 else if (mark == F_MID)
465 has_inner = true;
466 else if (mark == F_CORNER)
467 /* has_corner = true */ ; // currently unused, silencing warning (avogel)
468 else if (mark == F_VERT)
469 has_vert = true;
470 else
471 UG_THROW ("FractDimadapt:Fracture marks maybe not set correctly!");
472 }
473
474 if (has_inner && has_outer)
475 m_aaEdgeAuxMarks [edge] = F_VERT;
476 else if (has_vert)
477 m_aaEdgeAuxMarks [edge] = F_VERT;
478 else if (has_inner)
479 { // this is the inner side
480 m_aaEdgeAuxMarks [edge] = F_MID;
481 }
482 else
483 { // this is the outer side
484 m_aaEdgeAuxMarks [edge] = F_BND;
485 }
486 }
487 }
488 }
489 }
490
491
492}
493
497template <typename TDomain,typename TAlgebra>
499 number c,
500 number &rho,
501 number &d_rho
502 )
503{
504 UG_COND_THROW(strcmp(m_density_type, "NONE") !=0, "FractDimadapt: density not set: Use 'add_density'!");
505
506 if(strcmp(m_density_type,"linear")==0)
507 {
508 rho = m_rho_pw + ( m_rho_pb - m_rho_pw ) * c;
509 d_rho = m_rho_pb - m_rho_pw;
510 }
511 else
512 UG_THROW ("FractDimadapt: density type "<<m_density_type << "not yet considered: use 'linear'!");
513}
514
518template <typename TDomain,typename TAlgebra>
520 number c,
521 number &mu,
522 number &d_mu
523 )
524{
525 UG_COND_THROW(strcmp(m_viscosity_type, "NONE") !=0, "FractDimadapt: viscosity not set: Use 'add_viscosity'!");
526
527 if(strcmp(m_viscosity_type,"const")==0)
528 {
529 mu = m_zero_viscosity;
530 d_mu = 0.0;
531 }
532 else
533 UG_THROW ("FractDimadapt: density type "<<m_viscosity_type << "not yet considered: use 'const'!");
534}
535
536
540template <typename TDomain,typename TAlgebra>
541template <typename TGridFunction>
543 const std::vector<number> pnt,
544 TGridFunction& u,
545 number time
546 )
547{
548 UG_LOG("get_ave_val\n");
549
551 const position_accessor_type& posAcc = m_dom->position_accessor();
552
553 // create Multiindex
554 std::vector<DoFIndex> multInd;
555
556 number eps = 1E-10;
557
558 number c_1,c_2,c_ave=0,c_jump=0;
559 number p_1,p_2,p_ave=0,p_jump=0;
560
561 FILE *file;
562
563 MathVector<dim> eval_point;
564 for (int d=0;d < dim;d++)
565 eval_point[d] = pnt[d];
566 int toplevel = m_NumberLevels-1;
567 MathVector<dim> coords_1,coords_2,diff;
568
569 if(m_FirstFullLevel < 0)
570 UG_THROW ("FractDimadapt:get_ave_val: FirstFullLevel not set");
571
572
573
574 //Find Fracture mid node corresponding to eval point
575 int check = 0;
576 for (int k = 0; k < NumberFractNodes[toplevel]; k++)
577 {
578 coords_1 = posAcc[FractNode[toplevel][k][0]];
579 number dist = VecDistance(coords_1,eval_point);
580 if(dist < eps)
581 {
582 //if fracture is full-dimensional
583 //then integrate over fracture width.
584 if(m_FractureIsFullDimensional == 1)
585 {
586 //the nodes over which is integrated are stored in FractNode
587 Vertex * vert = FractNode[toplevel][k][0];
588 u.dof_indices(vert, 0, multInd);
589 c_ave = 2*DoFRef(u,multInd[0]);
590 u.dof_indices(vert, 1, multInd);
591 p_ave = 2*DoFRef(u,multInd[0]);
592 for (int i = 3; i < NumberFractVertNodes[toplevel][k]+3; i++)
593 {
594 u.dof_indices(FractNode[toplevel][k][i], 0, multInd);
595 c_ave += 2*DoFRef(u,multInd[0]);
596 u.dof_indices(FractNode[toplevel][k][i], 1, multInd);
597 p_ave += 2*DoFRef(u,multInd[0]);
598 }
599
600 coords_1 = posAcc[FractNode[toplevel][k][1]];
601 u.dof_indices(FractNode[toplevel][k][1], 0, multInd);
602 c_1=DoFRef(u,multInd[0]);
603 u.dof_indices(FractNode[toplevel][k][1], 1, multInd);
604 p_1=DoFRef(u,multInd[0]);
605 coords_2 = posAcc[FractNode[toplevel][k][2]];
606 u.dof_indices(FractNode[toplevel][k][2], 0, multInd);
607 c_2=DoFRef(u,multInd[0]);
608 u.dof_indices(FractNode[toplevel][k][2], 1, multInd);
609 p_2=DoFRef(u,multInd[0]);
610
611 // distinguish upper and lower boundary
612 //jump: upper-lower
613 VecSubtract(diff,coords_1,coords_2);
614 if(diff[dim-1]>1e-10) //coords_1 is upper
615 {
616 c_jump = c_1 - c_2;
617 p_jump = p_1 - p_2;
618 }
619 else if(diff[dim-1]<-1e-10) //coords_2 is upper
620 {
621 c_jump = c_2 - c_1;
622 p_jump = p_2 - p_1;
623 }
624 else if(fabs(diff[dim-1])<1e-10)
625 {
626 if(fabs(diff[0])<1e-10 && fabs(diff[dim-2])<1e-10)
627 {
628 UG_THROW ("FractDimadapt:get_ave_val: full-dim fracture with Fracture width 0!");
629 }
630 UG_THROW ("FractDimadapt:get_ave_val: Horizontal fracture not yet considered for jump");
631 }
632
633 c_ave += c_1 + c_2;
634 p_ave += p_1 + p_2;
635 c_ave /= (NumberFractVertNodes[toplevel][k]+1)*2+2;
636 p_ave /= (NumberFractVertNodes[toplevel][k]+1)*2+2;
637 }
638 else //fracture is low-dimensional
639 {
640 //average is stored in mid node
641 Vertex * vert = FractNode[toplevel][k][0];
642 u.dof_indices(vert, 0, multInd);
643 c_ave = DoFRef(u,multInd[0]);
644 u.dof_indices(vert, 1, multInd);
645 p_ave = DoFRef(u,multInd[0]);
646
647 u.dof_indices(FractNode[toplevel][k][1], 0, multInd);
648 c_1=DoFRef(u,multInd[0]);
649 u.dof_indices(FractNode[toplevel][k][1], 1, multInd);
650 p_1=DoFRef(u,multInd[0]);
651
652 u.dof_indices(FractNode[toplevel][k][2], 0, multInd);
653 c_2=DoFRef(u,multInd[0]);
654 u.dof_indices(FractNode[toplevel][k][2], 1, multInd);
655 p_2=DoFRef(u,multInd[0]);
656
657 //jump: upper-lower
658 c_jump = c_1 - c_2;
659 p_jump = p_1 - p_2;
660 MathVector<dim> shift = vert_shift(FractNode[toplevel][k][1]);
661 if(shift[dim-1]>1e-10) //c_1 is lower
662 {
663 c_jump = c_2 - c_1;
664 p_jump = p_2 - p_1;
665 }
666 else if(shift[dim-1]<1e-10) //c_1 is upper
667 {
668 c_jump = c_1 - c_2;
669 p_jump = p_1 - p_2;
670 }
671 else if(fabs(shift[dim-1])<1e-10)
672 {
673 if(fabs(shift[0])<1e-10 && fabs(shift[1])<1e-10)
674 {
675 UG_THROW ("FractDimadapt:get_ave_val: shift not set!");
676 }
677 UG_THROW ("FractDimadapt:get_ave_val: Horizontal fracture not yet considered for jump");
678 }
679 //add neglected pressure drop over fracture
680 //cf. e.g. [Reiter, S. et al. Models and simulations of variable-density flow
681 //in fractured porous media. IJSCE Vol. 9, Nos. 5/6, 2014]
682 if (m_shift == true)
683 {
684 number buffer = 0.0;
685 number density = 0.0;
686 density_func(c_ave,density,buffer);
687 number p_hydro = m_aperture*density*m_Gravity[dim-1];
688 p_jump += p_hydro;
689 }
690 }
691
692 check = 1;
693 k=NumberFractNodes[toplevel];
694 }
695 }
696 if(check==0)
697 UG_THROW ("FractDimadapt:get_ave_val: No inner fracture node at this position found!");
698
699 UG_LOG("\t t " << time<<" c_ave "<<c_ave<<" c_1 "<<c_1<<" c_2 "<<c_2<<" c_jump "<<c_jump <<"\n");
700 UG_LOG("\t t " << time<<" p_ave "<<p_ave<<" p_1 "<<p_1<<" p_2 "<<p_2<<" p_jump "<<p_jump <<"\n");
701
702 file = fopen("ave_c.dat","a");
703 fprintf(file, "%g %g %g\n",time,c_ave,c_jump);
704 fclose(file);
705 file = fopen("ave_p.dat","a");
706 fprintf(file, "%g %g %g\n",time,p_ave,p_jump);
707 fclose(file);
708}
709
713template <typename TDomain,typename TAlgebra>
714template <typename TGridFunction>
716 TGridFunction& u,
718 number omega_theta,
719 number time
720 )
721{
722 //DegeneratedLayerManager<TDomain::dim>* fractManager = NULL;
723 UG_LOG("evaluate_criterion\n");
724
725 if(m_permeability_f==0.0)
726 UG_THROW ("FractDimadapt: Permeability not set. Use 'add_permeability'");
727
728 if (! fractManager->is_closed ())
729 UG_THROW ("FractDimadapt:evaluate_crit: Fracture manager not closed");
730
732 typedef typename fract_manager_type::side_type DFside_type;
733 static const size_t maxLayerSideCorners = fract_manager_type::maxLayerSideCorners;
734
736 typedef typename geometry_traits<element_type>::const_iterator t_elem_iter;
737
739 const position_accessor_type& posAcc = m_dom->position_accessor();
740
741 //finite volume geometry
742 DimFV1Geometry<dim> fullgeo; //for full-dim
743 TFractFVGeom *lowgeo;
744 lowgeo = &GeomProvider<TFractFVGeom>::get (LFEID (LFEID::LAGRANGE, low_dim, 1), 1); //for low-dim
745
746
748
749 // create Multiindex
750 std::vector<DoFIndex> multInd;
751
752 number ViscosityIP;
753 number DensityIP;
754 number d_Density = 0.0;
755 number d_Visc = 0.0;
756
757 number theta_max = 0;
758 number theta_inv_max = 0;
759 number theta_min = 0;
760 number q_max = 0;
761 number q_rot_max = 0;
762 number test_max = 0;
763
764 number scale = m_permeability_f;
765
766 FILE *file;
767
768 //compute elementwise
769 for (size_t j = 0; j < m_fractSsGrp.size (); j++)
770 {
771 int si = m_fractSsGrp [j];
772 bool isFracture = fractManager->contains (si);
773
774 for (t_elem_iter iElem = m_spSH->template begin<element_type> (si,m_NumberLevels-1);
775 iElem != m_spSH->template end<element_type> (si,m_NumberLevels-1); ++iElem)
776 {
777 element_type * elem = *iElem;
778
779 // get vertices
780 const size_t numVertices = elem->num_vertices();
781
782 //extract corner coordinates
783 for(size_t i = 0; i < numVertices; ++i)
784 coCoord[i] = posAcc[elem->vertex(i)];
785
786 if(isFracture) //low-dim
787 {
788 typedef StdLinConsistentGravity<low_dim> TConsGravity;
789 TConsGravity ConsGravityMethod;
790 MathVector<low_dim> vConsGravity [maxLayerSideCorners];
791
792 size_t n_co, inner_side_idx, outer_side_idx;
793 size_t inner_side_corners [maxLayerSideCorners];
794 size_t outer_side_corners [maxLayerSideCorners];
795 DFside_type * inner_side, * outer_side;
796 size_t ass_co [2*maxLayerSideCorners];
797
798 number DensityCo[maxLayerSideCorners];
799 number ViscosityCo[maxLayerSideCorners];
800 number cValue[maxLayerSideCorners];
801 number pValue[maxLayerSideCorners];
802
803 // get the non-degenerated sides of the fracture element
804 fractManager->get_layer_sides (elem, n_co,
805 inner_side, inner_side_idx, inner_side_corners,
806 outer_side, outer_side_idx, outer_side_corners, ass_co);
807
808 // compute the FV geometry of the inner side
809 MathVector<dim> vSideCornerCoords [maxLayerSideCorners];
810 try
811 {
812 for (size_t co = 0; co < n_co; co++)
813 vSideCornerCoords [co] = posAcc [elem->vertex(inner_side_corners[co])];
814 lowgeo->update (inner_side, vSideCornerCoords, m_spSH.get());
815 }
816 UG_CATCH_THROW("EvaluateCriterion: Cannot update the Finite Volume Geometry for a fracture element.");
817 const size_t numSh = lowgeo->num_sh();
818 const size_t numScvf = lowgeo->num_scvf();
819
820 //get c,rho, mu and p in corners
821 for (size_t sh=0; sh < numSh; sh++)
822 {
823 size_t co = inner_side_corners[sh];
824 Vertex *vert = elem->vertex(co);
825 u.dof_indices(vert, 0, multInd);
826 cValue[sh] = DoFRef(u,multInd[0]);
827 density_func(cValue[sh],DensityCo[sh],d_Density);
828 viscosity_func(cValue[sh],ViscosityCo[sh],d_Visc);
829 u.dof_indices(vert, 1, multInd);
830 pValue[sh] = DoFRef(u,multInd[0]);
831 }
832
833 // Prepare the consistent gravity
834 try
835 {
836 ConsGravityMethod.template prepare<dim>
837 (vConsGravity, numSh, lowgeo->corners(), DensityCo, m_Gravity);
838 }
839 UG_CATCH_THROW ("EvaluateCriterion: Cannot prepare Consistent Gravity.");
840
841 for (size_t ip=0; ip < numScvf; ip++)
842 {
843 number absDarcy = 0;
844 number vorticity, q_rot;
845 number theta = 0;
846 number theta_inv = 0;
847 MathVector<dim> DarcyVel,Vel;
848 MathVector<dim> grad_c_ip;
849 MathVector<dim> grad_p_ip;
850 number c_ip;
851
852 const typename TFractFVGeom::SCVF& scvf = lowgeo->scvf(ip);
853
854 VecSet (grad_c_ip, 0.0);
855 VecSet (grad_p_ip, 0.0);
856 c_ip = 0;
857 for(size_t co = 0 ; co < scvf.num_sh(); ++co){
858 VecScaleAppend(grad_c_ip,cValue[co],scvf.global_grad(co));
859 VecScaleAppend(grad_p_ip,pValue[co],scvf.global_grad(co));
860 c_ip += cValue[co] * scvf.shape(co);
861 };
862 density_func(c_ip,DensityIP,d_Density);
863 viscosity_func(c_ip,ViscosityIP,d_Visc);
864
865 // DARCY VEL
866 // Compute rho * g (as the consistent gravity force)
867 ConsGravityMethod.template compute<dim>
868 (Vel, scvf.local_ip(), scvf.JTInv(), scvf.local_grad_vector(), vConsGravity);
869
870 // The pressure-gradient part:
871 VecScaleAppend (Vel, -1, grad_p_ip);
872 // The viscosity and permeability factor:
873 VecScale (DarcyVel, Vel, m_permeability_f / ViscosityIP);
874 absDarcy = VecLength(DarcyVel);
875 absDarcy = fabs(absDarcy);
876
877 // Q_ROT
878 //compute vorticity
879 vorticity = m_permeability_f / ViscosityIP * d_Density * m_Gravity[1] * grad_c_ip[0];
880
881 //compute q_rot
882 q_rot = m_aperture/2 * m_permeability_f/m_permeability_m * vorticity
883 * c_ip / omega_theta;
884
885 //compute theta
886 if(q_rot!=0)
887 theta = absDarcy / fabs(q_rot);
888 if(absDarcy != 0)
889 theta_inv = fabs(q_rot) / absDarcy;
890
891 //max
892 if(theta > theta_max)
893 theta_max = theta;
894 if(theta_inv > theta_inv_max)
895 theta_inv_max = theta_inv;
896 if(absDarcy > q_max)
897 q_max = absDarcy;
898 if(q_rot > q_rot_max)
899 q_rot_max = q_rot;
900
901 //min
902 if(theta < theta_min || theta_min==0)
903 theta_min = theta;
904 }
905 }
906 else //full-dim
907 {
908 std::vector<number> DensityCo(numVertices);
909 std::vector<number> ViscosityCo(numVertices);
910 std::vector<number> cValue(numVertices);
911 std::vector<number> pValue(numVertices);
912
913 // Consistent gravity and its derivative at corners
915 TConsGravity ConsGravityMethod;
917
918 // evaluate finite volume geometry
919 fullgeo.update(elem, &(coCoord[0]), u.domain()->subset_handler().get());
920 const size_t numSh = fullgeo.num_sh();
921 const size_t numScvf = fullgeo.num_scvf();
922
923 for (size_t co=0; co < numVertices; co++)
924 {
925 Vertex *vert = elem->vertex(co);
926 u.dof_indices(vert, 0, multInd);
927 cValue[co] = DoFRef(u,multInd[0]);
928 density_func(cValue[co],DensityCo[co],d_Density);
929 viscosity_func(cValue[co],ViscosityCo[co],d_Visc);
930 u.dof_indices(vert, 1, multInd);
931 pValue[co] = DoFRef(u,multInd[0]);
932 }
933
934 // Prepare the consistent gravity
935 try
936 {
937 ConsGravityMethod.template prepare<dim>
938 (vConsGravity, numSh, coCoord, &DensityCo[0], m_Gravity);
939 }
940 UG_CATCH_THROW ("EvaluateCriterion: Cannot prepare Consistent Gravity.");
941
942 for (size_t ip=0;ip < numScvf;ip++)
943 {
944 number absDarcy = 0;
945 number vorticity, q_rot;
946 number theta = 0;
947 number theta_inv = 0;
948 MathVector<dim> DarcyVel,Vel;
949 MathVector<dim> grad_c_ip;
950 MathVector<dim> grad_p_ip;
951 number c_ip;
952 number vort_test,test;
953
954 const typename DimFV1Geometry<dim>::SCVF& scvf = fullgeo.scvf(ip);
955
956 VecSet (grad_c_ip, 0.0);
957 VecSet (grad_p_ip, 0.0);
958 c_ip = 0;
959 for(size_t co = 0 ; co < scvf.num_sh(); ++co){
960 VecScaleAppend(grad_c_ip,cValue[co],scvf.global_grad(co));
961 VecScaleAppend(grad_p_ip,pValue[co],scvf.global_grad(co));
962 c_ip += cValue[co] * scvf.shape(co);
963 };
964 density_func(c_ip,DensityIP,d_Density);
965 viscosity_func(c_ip,ViscosityIP,d_Visc);
966
967 // DARCY VEL
968 // Compute rho * g (as the consistent gravity force)
969 ConsGravityMethod.template compute<dim>
970 (Vel, scvf.local_ip(), scvf.JTInv(), scvf.local_grad_vector(), vConsGravity);
971
972 // The pressure-gradient part:
973 VecScaleAppend (Vel, -1, grad_p_ip);
974
975 // The viscosity and permeability factor:
976 VecScale (DarcyVel, Vel, m_permeability_f / ViscosityIP); //MatVecMult if perm tensor
977 absDarcy = VecLength(DarcyVel);
978 absDarcy = fabs(absDarcy);
979
980 // Q_ROT
981 //compute vorticity
982 vorticity = m_permeability_f / ViscosityIP * d_Density * m_Gravity[1] * grad_c_ip[0];
983
984 vort_test = m_permeability_f / ViscosityIP * 25.0/1025.0 * 1000 / (1 - 25.0/1025.0 *c_ip) / (1 - 25.0/1025.0 *c_ip)* m_Gravity[1] * grad_c_ip[0];
985
986 //compute q_rot
987 q_rot = m_aperture/2 * m_permeability_f/m_permeability_m * vorticity * c_ip / omega_theta;
988
989 test = m_aperture * m_permeability_f/m_permeability_m * vort_test * c_ip / 50.0 /10.0 /0.25;
990
991 //compute theta
992 if(q_rot!=0)
993 theta = absDarcy / fabs(q_rot);
994 if(absDarcy != 0)
995 theta_inv = fabs(q_rot) / absDarcy;
996
997 test = fabs(test);
998
999 //max
1000 if(theta > theta_max)
1001 theta_max = theta;
1002 if(theta_inv > theta_inv_max)
1003 theta_inv_max = theta_inv;
1004 if(absDarcy > q_max)
1005 q_max = absDarcy;
1006 if(q_rot > q_rot_max)
1007 q_rot_max = q_rot;
1008 if(test > test_max)
1009 test_max = test;
1010
1011 //min
1012 if(theta < theta_min || theta_min==0)
1013 theta_min = theta;
1014 }
1015 }
1016 }
1017 }
1018
1019 //number theta = q_max / q_rot_max;
1020 number test = q_max / test_max;
1021 //UG_LOG("\n\t Max: q_max: "<< q_max<<" q_rot_max: " << q_rot_max<<" q_rot_UG3_max: " << test_max<<"\n");
1022 //UG_LOG("\n\t Max: theta_max: "<< theta_max <<" q_max / q_rot_max: " << theta <<" q_max / q_rot_UG3_max: " << test<<"\n");
1023
1024 UG_LOG("\t Min: theta_min: "<< theta_min<<" theta_inv_max: " << theta_inv_max<<"\n");
1025
1026 file = fopen("crit.dat","a");
1027 fprintf(file, "%g: theta_min: %g theta_inv_max: %g theta_UG3 %g\n",time,theta_min/scale,theta_inv_max*scale,test);
1028 fclose(file);
1029
1030 return theta_inv_max*scale;
1031}
1032
1033
1037template <typename TDomain,typename TAlgebra>
1038template <typename TGridFunction>
1040 TGridFunction& u,
1042 number omega_theta,
1043 number delta,
1044 number time
1045 )
1046{
1047 UG_LOG("check_transfer\n");
1048
1049 // do we have fractures?
1050 if (fractManager == NULL) return;
1051
1052 for (size_t i = 0; i < m_fractSsGrp.size (); i++)
1053 {
1054 int si = m_fractSsGrp [i];
1055
1056 bool isDegenerated = fractManager->contains (si);
1057
1058 UG_LOG("\n\t "<< isDegenerated << " "<< m_FractureIsFullDimensional<<"\n");
1059
1060 if(m_FractureIsFullDimensional == 1 && isDegenerated == true)
1061 fractManager->remove(m_spSH->get_subset_name(si));
1062
1063 isDegenerated = fractManager->contains (si);
1064 UG_LOG("\n\t "<< isDegenerated << " "<< m_FractureIsFullDimensional<<"\n");
1065
1066 number theta;
1067 theta = evaluate_criterion(u,fractManager,omega_theta,time);
1068
1069 if(theta < (1 - delta) )
1070 {
1071 UG_LOG("\n\t Should be low-dimensional\n");
1072 if(m_FractureIsFullDimensional == 1)
1073 {
1074 UG_LOG("\n\t switch\n");
1075 //first calculate average and store it in mid node
1076 transfer_full_to_low(u);
1077 //then transfer the grid (other inner fracture nodes are deleted)
1078 grid_transfer_full_to_low ();
1079 convert_end_triangles_to_quadris(u,fractManager);
1080 fractManager->add(m_spSH->get_subset_name(si));
1081 fractManager->close();
1082
1083 isDegenerated = fractManager->contains (si);
1084 UG_LOG("\n\t "<< isDegenerated << " "<< m_FractureIsFullDimensional<<"\n");
1085 }
1086 }
1087 if(theta > (1 + delta) )
1088 {
1089 UG_LOG("\n\t Should be full-dimensional\n");
1090 if(m_FractureIsFullDimensional == 0)
1091 {
1092 UG_LOG("\n\t switch\n");
1093 //first transfer grid
1094 convert_end_quadris_to_triangles(fractManager);
1095 grid_transfer_low_to_full ();
1096 //then calculate value of unknown for the new inner fracture nodes
1097 transfer_low_to_full(u);
1098 fractManager->remove(m_spSH->get_subset_name(si));
1099 fractManager->close();
1100
1101 isDegenerated = fractManager->contains (si);
1102 UG_LOG("\n\t "<< isDegenerated << " "<< m_FractureIsFullDimensional<<"\n");
1103 }
1104 }
1105 }
1106}
1107
1108
1114template <typename TDomain,typename TAlgebra>
1115template <typename TGridFunction>
1117 TGridFunction& u
1118 )
1119{
1120 // create Multiindex
1121 std::vector<DoFIndex> multInd;
1122
1123 UG_LOG("transfer full to low \n");
1124
1125 int lev = m_NumberLevels-1; //transfer is only needed on toplevel
1126 number c_ave,c_1,c_2;
1127 number p_ave,p_1,p_2;
1128 number p_1_korr,p_2_korr;
1129 number density = 0.0;
1130
1131 for (int k = 0; k < NumberFractNodes[lev]; k++)
1132 {
1133 //integrate over fracture width.
1134 //the nodes over which is integrated are stored in FractNode
1135 Vertex * vert = FractNode[lev][k][0];
1136 u.dof_indices(vert, 0, multInd);
1137 c_ave = 2*DoFRef(u,multInd[0]);
1138 u.dof_indices(vert, 1, multInd);
1139 p_ave = 2*DoFRef(u,multInd[0]);
1140
1141 for (int i = 3; i < NumberFractVertNodes[lev][k]+3; i++)
1142 {
1143 u.dof_indices(FractNode[lev][k][i], 0, multInd);
1144 c_ave += 2*DoFRef(u,multInd[0]);
1145 u.dof_indices(FractNode[lev][k][i], 1, multInd);
1146 p_ave += 2*DoFRef(u,multInd[0]);
1147 }
1148
1149 u.dof_indices(FractNode[lev][k][1], 0, multInd);
1150 c_1=DoFRef(u,multInd[0]);
1151 u.dof_indices(FractNode[lev][k][1], 1, multInd);
1152 p_1=DoFRef(u,multInd[0]);
1153 u.dof_indices(FractNode[lev][k][2], 0, multInd);
1154 c_2=DoFRef(u,multInd[0]);
1155 u.dof_indices(FractNode[lev][k][2], 1, multInd);
1156 p_2=DoFRef(u,multInd[0]);
1157
1158 c_ave += c_1 + c_2;
1159 p_ave += p_1 + p_2;
1160 c_ave /= (NumberFractVertNodes[lev][k]+1)*2+2;
1161 p_ave /= (NumberFractVertNodes[lev][k]+1)*2+2;
1162
1163 //correct pressure (vertices are shifted, therefore hydrostatic pressure needs to be adapted)
1164 if(m_shift == true)
1165 {
1166 number buffer = 0.0;
1167 density_func(c_1,density,buffer);
1168 MathVector<dim> shift = vert_shift(FractNode[lev][k][1]);
1169 p_1_korr = p_1 + shift[dim-1]*density*m_Gravity[dim-1];
1170 density_func(c_2,density,buffer);
1171 shift = vert_shift(FractNode[lev][k][2]);
1172 p_2_korr = p_2 + shift[dim-1]*density*m_Gravity[dim-1];
1173
1174 //write corrected pressure in bnd_verts
1175 u.dof_indices(FractNode[lev][k][1], 1, multInd);
1176 DoFRef(u,multInd[0]) = p_1_korr;
1177 u.dof_indices(FractNode[lev][k][2], 1, multInd);
1178 DoFRef(u,multInd[0]) = p_2_korr;
1179 }
1180
1181 //write average in mid_vert
1182 u.dof_indices(vert, 0, multInd);
1183 DoFRef(u,multInd[0]) = c_ave;
1184 u.dof_indices(vert, 1, multInd);
1185 DoFRef(u,multInd[0]) = p_ave;
1186 }
1187}
1188
1196template <typename TDomain,typename TAlgebra>
1198 number bnd[2][2],
1199 number mid[2],
1200 MathVector<dim> bndpoint[2],
1201 number param[2][3] //return value
1202 )
1203{
1204 number a[2][2],b[2][2],tem,temp,temp1,temp2,temp4,temp5;
1205 int i,j;
1206 int n=2,m=2;
1207 int p,q;
1208 number length;
1209 MathVector<dim> vec,x;
1210
1211 //do not multiply mistakes!!
1212 for(i=0;i<2;i++)
1213 {
1214 if(fabs(bnd[i][0])<1E-10 && bnd[i][0]<0)
1215 bnd[i][0]=0;
1216 }
1217 if(fabs(mid[0])<1E-10 && mid[0]<0)
1218 mid[0]=0;
1219
1220 //|x_2 - x_1|
1221 VecSubtract(x,bndpoint[1],bndpoint[0]);
1222 length = VecLength(x);
1223
1224 a[0][0]=length*length;
1225 a[0][1]=length;
1226 a[1][0]=length*length*length/3;
1227 a[1][1]=length*length/2;
1228
1229 //Calculate Inverse of A=a_ij
1230 for(i=0;i<n;i++)
1231 {
1232 for(j=0;j<m;j++)
1233 {
1234 if(i==j)
1235 b[i][j]=1;
1236 else
1237 b[i][j]=0;
1238 }
1239 }
1240 for(i=0;i<n;i++)
1241 {
1242 temp=a[i][i];
1243 if(temp<0)
1244 temp=temp*(-1);
1245 p=i;
1246 for(j=i+1;j<n;j++)
1247 {
1248 if(a[j][i]<0)
1249 tem=a[j][i]*(-1);
1250 else
1251 tem=a[j][i];
1252 if(temp<0)
1253 temp=temp*(-1);
1254 if(tem>temp)
1255 {
1256 p=j;
1257 temp=a[j][i];
1258 }
1259 }
1260 //row exchange in both the matrix
1261 for(j=0;j<n;j++)
1262 {
1263 temp1=a[i][j];
1264 a[i][j]=a[p][j];
1265 a[p][j]=temp1;
1266 temp2=b[i][j];
1267 b[i][j]=b[p][j];
1268 b[p][j]=temp2;
1269 }
1270 //dividing the row by a[i][i]
1271 temp4=a[i][i];
1272 for(j=0;j<n;j++)
1273 {
1274 a[i][j]=(number)a[i][j]/temp4;
1275 b[i][j]=(number)b[i][j]/temp4;
1276 }
1277 //making other elements 0 in order to make the matrix a[][] an indentity matrix and obtaining a inverse b[][] matrix
1278 for(q=0;q<n;q++)
1279 {
1280 if(q==i)
1281 continue;
1282 temp5=a[q][i];
1283 for(j=0;j<n;j++)
1284 {
1285 a[q][j]=a[q][j]-(temp5*a[i][j]);
1286 b[q][j]=b[q][j]-(temp5*b[i][j]);
1287 }
1288 }
1289 //b is inverse
1290 }
1291
1292 for(i=0;i<2;i++)
1293 {
1294 vec[0] = (bnd[1][i]-bnd[0][i]); //u_2 - u_1
1295 vec[1] = (mid[i]-bnd[0][i])*length; // |x_2-x_1|*(u_mid - u_1)
1296 param[i][0] = b[0][0]*vec[0] + b[0][1]*vec[1];
1297 param[i][1] = b[1][0]*vec[0] + b[1][1]*vec[1];
1298 param[i][2] = bnd[0][i]; // u_1
1299 }
1300}
1301
1307template <typename TDomain,typename TAlgebra>
1308template <typename TGridFunction>
1310 TGridFunction& u
1311 )
1312{
1313 // create Multiindex
1314 std::vector<DoFIndex> multInd;
1315
1317 const position_accessor_type& posAcc = m_dom->position_accessor();
1318
1319 UG_LOG("transfer low to full \n");
1320
1321 int lev = m_NumberLevels-1; //transfer only needed on toplevel
1322 for (int k = 0; k < NumberFractNodes[lev]; k++)
1323 {
1324 number mid[2],bnd[2][2];
1325 number inner[2];
1326 MathVector<dim> bndpoint[2];
1327 MathVector<dim> calcpoint;
1328 number param[2][3];
1329 number x;
1330 number density = 0.0;
1331 number buffer = 0.0; //d_dens not needed here
1332
1333 //get values in mid node (=average)
1334 Vertex * vert = FractNode[lev][k][0];
1335 u.dof_indices(vert, 0, multInd);
1336 mid[0] = DoFRef(u,multInd[0]);
1337 u.dof_indices(vert, 1, multInd);
1338 mid[1] = DoFRef(u,multInd[0]);
1339
1340 //get values in bnd nodes
1341 // and correct pressure (vertices are shifted, therefore hydrostatic pressure needs to be adapted)
1342 // bnd 1
1343 vert = FractNode[lev][k][1];
1344 u.dof_indices(vert, 0, multInd);
1345 bnd[0][0]=DoFRef(u,multInd[0]);
1346 u.dof_indices(vert, 1, multInd);
1347 bnd[0][1]=DoFRef(u,multInd[0]);
1348 bndpoint[0]=posAcc[vert];
1349 //correct p
1350 if(m_shift == true)
1351 {
1352 density_func(bnd[0][0],density,buffer);
1353 MathVector<dim> shift = vert_shift(vert);
1354 bnd[0][1] = bnd[0][1] - shift[dim-1]*density*m_Gravity[dim-1];
1355 DoFRef(u,multInd[0]) = bnd[0][1];
1356 }
1357
1358 // bnd 2
1359 vert = FractNode[lev][k][2];
1360 u.dof_indices(vert, 0, multInd);
1361 bnd[1][0]=DoFRef(u,multInd[0]);
1362 u.dof_indices(vert, 1, multInd);
1363 bnd[1][1]=DoFRef(u,multInd[0]);
1364 bndpoint[1]=posAcc[vert];
1365 //correct p
1366 if(m_shift == true)
1367 {
1368 density_func(bnd[1][0],density,buffer);
1369 MathVector<dim> shift = vert_shift(vert);
1370 bnd[1][1] = bnd[1][1] - shift[dim-1]*density*m_Gravity[dim-1];
1371 DoFRef(u,multInd[0]) = bnd[1][1];
1372 }
1373
1374
1375 //assume quadratic behaviour of unknowns in fracture
1376 //calculate parameters a,b,c
1377 calculate_interpolation(bnd,mid,bndpoint,param);
1378 size_t use_linear = 0;
1379 for (int i = 0; i < NumberFractVertNodes[lev][k]+3; i++)
1380 {
1381 //boundary values are not changed
1382 // though, considering them here, should not change anything.
1383 if(i==1 || i==2)
1384 continue;
1385 vert = FractNode[lev][k][i];
1386 calcpoint = posAcc[vert];
1387 //|x - x_1|
1388 VecSubtract(calcpoint,bndpoint[0],calcpoint);
1389 x = VecLength(calcpoint);
1390 //calculate and set value
1391 for(size_t j=0; j<2; j++)
1392 {
1393 inner[j] = param[j][0]*x*x + param[j][1]*x + param[j][2]; //f(x)= ax^2+bx+c
1394// UG_LOG("\t inner " << posAcc[vert] <<" "<< bnd[0][j] <<" "<<bnd[1][j] <<" "
1395// <<mid[j]<<" "<<inner[j]<< " \n" );
1396 u.dof_indices(vert, j, multInd);
1397 DoFRef(u,multInd[0]) = inner[j];
1398 }
1399
1400 //if computed unknown are out of bounds (e.g. negative concentration)
1401 //use a linear interpolation instead
1402 if(inner[0]<-1e-10 || inner[0]>1 || inner[1]<-1e-10)
1403 {
1404 UG_LOG ("FractDimadapt:transfer_low_to_full: c or p neg. Use linear fct instead");
1405 use_linear = 1;
1406 i=NumberFractVertNodes[lev][k]+3;
1407 }
1408 }
1409 if(use_linear == 1)
1410 {
1411 for (int i = 0; i < NumberFractVertNodes[lev][k]+3; i++)
1412 {
1413 //boundary values are not changed
1414 if(i==1 || i==2)
1415 continue;
1416 vert = FractNode[lev][k][i];
1417 //|x - x_1|
1418 VecSubtract(calcpoint,bndpoint[0],posAcc[vert]);
1419 x = VecLength(calcpoint);
1420 //|x2 - x_1|
1421 VecSubtract(calcpoint,bndpoint[0],bndpoint[1]);
1422 x = x / VecLength(calcpoint);
1423 //calculate and set value
1424 for(size_t j=0; j<2; j++)
1425 {
1426 inner[j] = (1-x) * bnd[0][j] + x * bnd[1][j];
1427// UG_LOG("\t inner " << posAcc[vert] <<" "<< bnd[0][j] <<" "<<bnd[1][j] <<" "
1428// <<mid[j]<<" "<<inner[j]<< " \n" );
1429 u.dof_indices(vert, j, multInd);
1430 DoFRef(u,multInd[0]) = inner[j];
1431 }
1432 }
1433 }
1434
1435 }
1436}
1437
1441template <typename TDomain,typename TAlgebra>
1443{
1444 typedef typename geometry_traits<element_type>::const_iterator t_elem_iter;
1445
1446 MultiGrid * pMG = (MultiGrid *) (m_spSH->multi_grid ());
1447
1449 typename Grid::traits<Edge>::secure_container edge_list;
1450
1451 if(m_FirstFullLevel < 0)
1452 UG_THROW ("FractDimadapt:grid_transfer_full_to_low: FirstFullLevel not set");
1453
1454 typedef typename domain_type::position_attachment_type pos_att_type;
1455 pos_att_type aPos = m_dom->position_attachment();
1457 aaPos.access (*pMG, aPos);
1458
1459 UG_LOG("grid transfer full to low \n");
1460
1461 //begin of grid adaption noticed by messenger
1463
1464 //delete triangles (because they have no vert fract node)
1465 //todo: check for 3d. edges/sides??
1466 for (int lev = m_FirstFullLevel; lev < m_NumberLevels; lev++)
1467 {
1468 for(int i=0; i<4; i++)
1469 {
1470 element_type * elem = CornerTriangleList[lev][i];
1471
1472 pMG->associated_elements_sorted (edge_list, elem);
1473
1474 std::vector<Edge*> edge_to_erase(edge_list.size ());
1475 int counter = 0;
1476 for (size_t j = 0; j < edge_list.size (); j++)
1477 {
1478 Edge * edge = edge_list [j];
1479 if(edge_mark(edge)==F_MID || edge_mark(edge)==F_BND)
1480 continue;
1481 edge_to_erase[counter]= edge;
1482 counter++;
1483 }
1484 for(int j=0; j<counter; j++)
1485 {
1486 pMG->erase(edge_to_erase[j]);
1487 }
1488 }
1489 }
1490
1491 //delete vert fract nodes (then all edges and faces depending on them are deleted too)
1492 for (int lev = 0; lev < m_NumberLevels; lev++)
1493 {
1494 for (int k = 0; k < NumberFractNodes[lev]; k++)
1495 {
1496 for (int i = 3; i < NumberFractVertNodes[lev][k]+3; i++)
1497 {
1498 pMG->erase(FractNode[lev][k][i]);
1499 }
1500 NumberFractVertNodes[lev][k] = 0;
1501 }
1502 }
1503
1504 //insert new elements
1505 int baselev = m_FirstFullLevel-1;
1506 int toplev = m_NumberLevels-1;
1507 for (int lev = baselev; lev < toplev; lev++)
1508 {
1509 for (size_t i = 0; i < m_fractSsGrp.size (); i++)
1510 {
1511 int si = m_fractSsGrp [i];
1512 t_elem_iter list_end = m_spSH->template end<element_type> (si, lev);
1513 for (t_elem_iter iElem = m_spSH->template begin<element_type> (si, lev);
1514 iElem != list_end; ++iElem)
1515 {
1516 element_type * elem = *iElem;
1517
1518 //Find the corner vertices for the new elements
1519 int numvert = elem->num_vertices ();
1520 Vertex *v[4];//MaxNumCornerElements
1521 Vertex *v2[4];
1522 pMG->associated_elements_sorted (edge_list, elem);
1523
1524 //for each element two new elems need to be created
1525 int counter = 0;
1526 int counter2 = 0;
1527 int done = 0;
1528 int triangle_done = 0;
1529 for (size_t j = 0; j < edge_list.size (); j++)
1530 {
1531 Edge * edge = edge_list [j];
1532 //edge has no vertex children: both endpoints are corners of new elem
1533 if(pMG->num_child_vertices(edge)==0)
1534 {
1535 //Find edge co numbering in correspondence to elem co numbering
1536 int num0,num1;
1537 for(int k=0; k<numvert; k++)
1538 {
1539 if(elem->vertex(k)==edge->vertex(0))
1540 {
1541 if(elem->vertex((k+1)%numvert)==edge->vertex(1))//std
1542 {
1543 num0 = 0;
1544 num1 = 1;
1545 }
1546 else if(elem->vertex((numvert+k-1)%numvert)==edge->vertex(1))
1547 {
1548 num0 = 1;
1549 num1 = 0;
1550 }
1551 else
1552 UG_THROW ("FractDimadapt:grid_transfer_full_to_low: Elem Edge numbering\n");
1553 }
1554 }
1555 if(done==0) //corners for the first elem
1556 {
1557 v[counter] = pMG->get_child_vertex(edge->vertex(num0));
1558 counter++;
1559 v[counter] = pMG->get_child_vertex(edge->vertex(num1));
1560 counter++;
1561 done = 1;
1562 }
1563 else //corners for the second elem
1564 {
1565 v2[counter2] = pMG->get_child_vertex(edge->vertex(num0));
1566 counter2++;
1567 v2[counter2] = pMG->get_child_vertex(edge->vertex(num1));
1568 counter2++;
1569 done = 1;
1570 }
1571 }
1572 else //edge has vertex child: this is corner of new elem
1573 {
1574 v[counter] = pMG->get_child_vertex(edge);
1575 counter++;
1576 if(numvert==3 && triangle_done ==0) //for triangle
1577 {
1578 for(int k=0; k<numvert; k++)
1579 {
1580 Vertex *vert =elem->vertex(k);
1581 if(vert_mark(vert)==F_CORNER)
1582 {
1583 if(elem->vertex(k)==edge->vertex(0))
1584 {
1585 if(elem->vertex((k+1)%numvert)==edge->vertex(1))//std
1586 {
1587 v2[counter2] = pMG->get_child_vertex(vert);
1588 counter2++;
1589 v2[counter2] = pMG->get_child_vertex(edge);
1590 counter2++;
1591 }
1592 else if(elem->vertex((numvert+k-1)%numvert)==edge->vertex(1))
1593 {
1594 v2[counter2] = pMG->get_child_vertex(edge);
1595 counter2++;
1596 v2[counter2] = pMG->get_child_vertex(vert);
1597 counter2++;
1598 }
1599 else
1600 UG_THROW ("FractDimadapt:grid_transfer_full_to_low: Triangle\n");
1601 }
1602 else if(elem->vertex(k)==edge->vertex(1))
1603 {
1604 if(elem->vertex((k+1)%numvert)==edge->vertex(0))
1605 {
1606 v2[counter2] = pMG->get_child_vertex(edge);
1607 counter2++;
1608 v2[counter2] = pMG->get_child_vertex(vert);
1609 counter2++;
1610 }
1611 else if(elem->vertex((numvert+k-1)%numvert)==edge->vertex(0))//std
1612 {
1613 v2[counter2] = pMG->get_child_vertex(vert);
1614 counter2++;
1615 v2[counter2] = pMG->get_child_vertex(edge);
1616 counter2++;
1617 }
1618 else
1619 UG_THROW ("FractDimadapt:grid_transfer_full_to_low: Triangle\n");
1620 }
1621 else
1622 UG_THROW ("FractDimadapt:grid_transfer_full_to_low:Triangle\n");
1623 }
1624 }
1625 triangle_done = 1;
1626 }
1627 else //quadrilateral and second triangle side
1628 {
1629 v2[counter2] = pMG->get_child_vertex(edge);
1630 counter2++;
1631 }
1632 }
1633 }
1634
1635 //for quadirlaterals two new quadrilaterals are created
1636 if(numvert==4)
1637 {
1638 if(counter!=4)
1639 UG_THROW ("FractDimadapt:grid_transfer_full_to_low: wrong number corners"<<counter<<"\n");
1640 pMG->create<Quadrilateral>(QuadrilateralDescriptor(v[0],v[1],v[2],v[3]),elem);
1641 if(counter2!=4)
1642 UG_THROW ("FractDimadapt:grid_transfer_full_to_low: wrong number corners"<<counter2<<"\n");
1643 pMG->create<Quadrilateral>(QuadrilateralDescriptor(v2[0],v2[1],v2[2],v2[3]),elem);
1644 }
1645 else if(numvert==3)//for triangles one quadrilateral and one triangle are created
1646 {
1647 if(counter!=4)
1648 UG_THROW ("FractDimadapt:grid_transfer_full_to_low: wrong number corners"<<counter<<"\n");
1649 pMG->create<Quadrilateral>(QuadrilateralDescriptor(v[0],v[1],v[2],v[3]),elem);
1650 if(counter2!=3)
1651 UG_THROW ("FractDimadapt:grid_transfer_full_to_low: wrong number corners"<<counter2<<"\n");
1652 pMG->create<Triangle>(TriangleDescriptor(v2[0],v2[1],v2[2]),elem);
1653 }
1654 }
1655 }
1656
1657 }
1658
1659 //shift fracture boundary vertices so that fracture has width 0
1660 if(m_shift == true)
1661 {
1662 for (int lev = 0; lev < m_NumberLevels; lev++)
1663 {
1664 for (int k = 0; k < NumberFractNodes[lev]; k++)
1665 {
1666 MathVector<dim> newcoord;
1667 if(FractNode[lev][k][1]!=NULL && FractNode[lev][k][2]!=NULL)
1668 {
1669 MathVector<dim> shift = vert_shift(FractNode[lev][k][1]);
1670
1671 //Todo SHIFT Debug
1672 number debug_shift = 1e-10;
1673 if(shift[1]>0)
1674 shift[1] += debug_shift;
1675 else if (shift[1]<0)
1676 shift[1] -= debug_shift;
1677
1678 VecAdd(newcoord,aaPos[FractNode[lev][k][1]],shift);
1679 aaPos[FractNode[lev][k][1]] = newcoord;
1680
1681
1682 shift = vert_shift(FractNode[lev][k][2]);
1683
1684 //Todo SHIFT Debug
1685 if(shift[1]>0)
1686 shift[1] += debug_shift;
1687 else if (shift[1]<0)
1688 shift[1] -= debug_shift;
1689
1690 VecAdd(newcoord,aaPos[FractNode[lev][k][2]],shift);
1691 aaPos[FractNode[lev][k][2]] = newcoord;
1692 }
1693 }
1694 }
1695 }
1696
1697
1698 m_FractureIsFullDimensional = 0;
1699
1700 //end of grid adaption noticed by messenger
1702
1703}
1704
1708template <typename TDomain,typename TAlgebra>
1710{
1711 typedef typename geometry_traits<element_type>::const_iterator t_elem_iter;
1712
1713 MultiGrid * pMG = (MultiGrid *) (m_spSH->multi_grid ());
1714
1716 typename Grid::traits<Edge>::secure_container edge_list;
1717
1718 typedef typename domain_type::position_attachment_type pos_att_type;
1719 pos_att_type aPos = m_dom->position_attachment();
1721 aaPos.access (*pMG, aPos);
1722
1723 if(m_FirstFullLevel < 0)
1724 UG_THROW ("FractDimadapt:grid_transfer_low_to_full: FirstFullLevel not set");
1725
1726 UG_LOG("grid transfer low to full \n");
1727
1728 //begin of grid adaption noticed by messenger
1730
1731 //shift fracture boundary vertices so that fracture has no longer width 0
1732 if(m_shift == true)
1733 {
1734 for (int lev = 0; lev < m_NumberLevels; lev++)
1735 {
1736 for (int k = 0; k < NumberFractNodes[lev]; k++)
1737 {
1738 if(FractNode[lev][k][1]!=NULL && FractNode[lev][k][2]!=NULL)
1739 {
1740 MathVector<dim> newcoord;
1741 MathVector<dim> shift = vert_shift(FractNode[lev][k][1]);
1742
1743 //Todo SHIFT Debug
1744 number debug_shift = 1e-10;
1745 if(shift[1]>0)
1746 shift[1] -= debug_shift;
1747 else if (shift[1]<0)
1748 shift[1] += debug_shift;
1749
1750 VecSubtract(newcoord,aaPos[FractNode[lev][k][1]],shift);
1751 aaPos[FractNode[lev][k][1]] = newcoord;
1752 shift = vert_shift(FractNode[lev][k][2]);
1753
1754 //Todo SHIFT Debug
1755 if(shift[1]>0)
1756 shift[1] -= debug_shift;
1757 else if (shift[1]<0)
1758 shift[1] += debug_shift;
1759
1760 VecSubtract(newcoord,aaPos[FractNode[lev][k][2]],shift);
1761 aaPos[FractNode[lev][k][2]] = newcoord;
1762 }
1763 }
1764 }
1765 }
1766
1767 //todo: check for 3d. edges/sides??
1768
1769 //delete vert edges. Then all fracture elems are deleted as well
1770 for (int lev = m_FirstFullLevel; lev < m_NumberLevels; lev++)
1771 {
1772 for (size_t i = 0; i < m_fractSsGrp.size (); i++)
1773 {
1774 int si = m_fractSsGrp [i];
1775 Edge * edge_to_erase[200];
1776 int counter = 0;
1777 t_elem_iter list_end = m_spSH->template end<element_type> (si, lev);
1778 for (t_elem_iter iElem = m_spSH->template begin<element_type> (si, lev);
1779 iElem != list_end; ++iElem)
1780 {
1781 element_type * elem = *iElem;
1782 pMG->associated_elements_sorted (edge_list, elem);
1783 for (size_t j = 0; j < edge_list.size (); j++)
1784 {
1785 Edge * edge = edge_list [j];
1786 if(edge_mark(edge)==F_MID || edge_mark(edge)==F_BND || edge_mark(edge)==F_NONE)
1787 continue;
1788 edge_to_erase[counter]= edge;
1789 m_aaEdgeAuxMarks [edge] = F_NONE; // mark as none to avoid double counting
1790 counter++;
1791 if(counter==200)
1792 UG_THROW ("FractDimadapt:grid_transfer_low_to_full: number of edges out of bounds");
1793 }
1794 }
1795 for(int j=0; j<counter; j++)
1796 {
1797 pMG->erase(edge_to_erase[j]);
1798 }
1799 }
1800 }
1801
1802 //now insert new vertices
1803 int baselev = m_FirstFullLevel-1;
1804 int toplev = m_NumberLevels-1;
1805 for (int lev = baselev; lev < toplev; lev++)
1806 {
1807 for (size_t i = 0; i < m_fractSsGrp.size (); i++)
1808 {
1809 int si = m_fractSsGrp [i];
1810 t_elem_iter list_end = m_spSH->template end<element_type> (si, lev);
1811 for (t_elem_iter iElem = m_spSH->template begin<element_type> (si, lev);
1812 iElem != list_end; ++iElem)
1813 {
1814 element_type * elem = *iElem;
1815 Vertex* v[4][4];
1816 if(elem->num_vertices ()==4)
1817 {
1818 //insert vrt and calculate new position
1819 Vertex *newvrt = *pMG->create<RegularVertex>(elem);
1820 aaPos[newvrt] = CalculateCenter(elem, aaPos);
1821 //insert vertex recursively on finer grids.
1822 Vertex *newvrt_old = newvrt;
1823 for(int recursive_lev = lev; recursive_lev < toplev-1; recursive_lev++)
1824 {
1825 newvrt = *pMG->create<RegularVertex>(newvrt_old);
1826 aaPos[newvrt] = aaPos[newvrt_old];
1827 newvrt_old = newvrt;
1828 }
1829 }
1830
1831 pMG->associated_elements_sorted (edge_list, elem);
1832 for (size_t j = 0; j < edge_list.size (); j++)
1833 {
1834 Edge * edge = edge_list [j];
1835 if(pMG->num_child_vertices(edge)==0)
1836 {
1837 //insert vrt and calculate new position
1838 Vertex *newvrt = *pMG->create<RegularVertex>(edge);
1839 aaPos[newvrt] = CalculateCenter(edge, aaPos);
1840 //insert corresponding edges
1841 pMG->create<RegularEdge>(EdgeDescriptor(pMG->get_child_vertex(edge->vertex(0)),newvrt),edge);
1842 pMG->create<RegularEdge>(EdgeDescriptor(newvrt,pMG->get_child_vertex(edge->vertex(1))),edge);
1843 //insert vertex recursively on finer grids.
1844 Vertex *newvrt_old = newvrt;
1845 for(int recursive_lev = lev; recursive_lev < toplev-1; recursive_lev++)
1846 {
1847 newvrt = *pMG->create<RegularVertex>(newvrt_old);
1848 aaPos[newvrt] = aaPos[newvrt_old];
1849 newvrt_old = newvrt;
1850 }
1851 }
1852 }
1853
1854 //list corners of new elems
1855 if(elem->num_vertices ()==4)
1856 {
1857 for(size_t j = 0; j < 4; ++j)
1858 {
1859 v[j][0] = pMG->get_child_vertex(elem->vertex(j));
1860 // v[j][1] = pMG->get_child_vertex(pMG->get_edge(elem, j));
1861 v[j][1] = pMG->get_child_vertex(edge_list [j]);
1862 v[j][2] = pMG->get_child_vertex(elem);
1863 v[j][3] = pMG->get_child_vertex(edge_list [(j+3)%edge_list.size ()]);
1864 //UG_LOG("vrtlist quad " <<posAcc[v[j][0]]<<" "<<posAcc[v[j][1]]<<" "<<posAcc[v[j][2]]<<" "<<posAcc[v[j][3]]<<"\n ");
1865 pMG->create<Quadrilateral>(QuadrilateralDescriptor(v[j][0],v[j][1],v[j][2],v[j][3]),elem);
1866 }
1867 }
1868 else if(elem->num_vertices ()==3)
1869 {
1870 for (size_t j = 0; j < edge_list.size (); j++)
1871 {
1872 Edge * edge = edge_list [j];
1873 v[j][0] = pMG->get_child_vertex(elem->vertex(j));
1874 v[j][1] = pMG->get_child_vertex(edge);
1875 v[j][2] = pMG->get_child_vertex(edge_list [(j+2)%edge_list.size ()]);
1876 //UG_LOG("vrtlist tri 1 " <<posAcc[v[j][0]]<<" "<<posAcc[v[j][1]]<<" "<<posAcc[v[j][2]]);
1877 pMG->create<Triangle>(TriangleDescriptor(v[j][0],v[j][1],v[j][2]),elem);
1878 }
1879 v[3][0] = pMG->get_child_vertex(edge_list [0]);
1880 v[3][1] = pMG->get_child_vertex(edge_list [1]);
1881 v[3][2] = pMG->get_child_vertex(edge_list [2]);
1882 //UG_LOG("vrtlist tri 2 " <<posAcc[v[3][0]]<<" "<<posAcc[v[3][1]]<<" "<<posAcc[v[3][2]]);
1883 pMG->create<Triangle>(TriangleDescriptor(v[3][0],v[3][1],v[3][2]),elem);
1884 }
1885 else
1886 UG_THROW ("FractDimadapt:grid_transfer_low_to_full: only triangles and quadrilaterals so far");
1887 }
1888 }
1889 }
1890
1891 m_FractureIsFullDimensional = 1;
1892
1893 //end of grid adaption noticed by messenger
1895}
1896
1902template <typename TDomain,typename TAlgebra>
1903template <typename TGridFunction>
1905 TGridFunction& u,
1907)
1908{
1909 UG_LOG("convert_tri_to_quad \n");
1910
1911 // create Multiindex
1912 std::vector<DoFIndex> multInd;
1913
1914 typedef typename geometry_traits<element_type>::const_iterator t_elem_iter;
1915
1916 MultiGrid * pMG = (MultiGrid *) (m_spSH->multi_grid ());
1917
1918 typename Grid::traits<Edge>::secure_container edge_list;
1919
1920
1921 typedef typename domain_type::position_attachment_type pos_att_type;
1922 pos_att_type aPos = m_dom->position_attachment();
1924 aaPos.access (*pMG, aPos);
1925
1926
1927 //begin of grid adaption noticed by messenger
1929
1930 //each new inserted vertex is saved to be used on the next level as parent
1931 const size_t max_number_deg_quadris = 2;
1932 Vertex * new_vrt_father[max_number_deg_quadris];
1933 Edge * new_degedge_father[max_number_deg_quadris];
1934 Edge * new_fulledge_father[max_number_deg_quadris];
1935 Face* new_face1_father[max_number_deg_quadris];
1936 size_t number_new_vrts = 0;
1937
1938 size_t max_verts = max_number_deg_quadris * m_NumberLevels;
1939 std::vector<std::vector<Vertex*> > vert_pairs(max_verts);
1940 for(size_t i = 0; i < vert_pairs.size(); ++i) vert_pairs[i].resize(2);
1941// Vertex * vert_pairs[max_verts][2];
1942 size_t vert_count = 0;
1943
1944 //degenerated fractures in UG4 can only end with quadrilaterals
1945 //in the full-dim case the fractures end with triangles
1946 for (int lev = 0; lev < m_NumberLevels; lev++)
1947 {
1948 size_t triangle_counter = 0;
1949 Edge * corneredge[4];
1950 Face* cornerface[4];
1951 Vertex * cornervrt[4];
1952 Vertex * vrtlist[4][4];
1953 number sign[4];
1954 size_t partner[4];
1955 size_t edgenum[4]; //for ordering
1956
1957
1958
1959 //find end elements of fracture (triangle + cornernode)
1960 for (size_t h = 0; h < m_fractSsGrp.size (); h++)
1961 {
1962 int si = m_fractSsGrp [h];
1963 for (t_elem_iter iElem = m_spSH->template begin<element_type> (si, lev);
1964 iElem != m_spSH->template end<element_type> (si, lev); ++iElem)
1965 {
1966 element_type * elem = *iElem;
1967
1968 if(elem->num_vertices()==3)
1969 {
1970 pMG->associated_elements_sorted (edge_list, elem);
1971 for (size_t j = 0; j < edge_list.size (); j++)
1972 {
1973 Edge * edge = edge_list [j];
1974 if(edge_mark(edge)==F_MID)
1975 {
1976 if(vert_mark(edge->vertex(0))==F_CORNER)
1977 {
1978 cornervrt[triangle_counter] = edge->vertex(0);
1979 number s = aaPos[edge->vertex(1)][0] - aaPos[edge->vertex(0)][0];
1980 sign[triangle_counter] = s/(fabs(s));
1981 }
1982 else if(vert_mark(edge->vertex(1))==F_CORNER)
1983 {
1984 cornervrt[triangle_counter] = edge->vertex(1);
1985 number s = aaPos[edge->vertex(0)][0] - aaPos[edge->vertex(1)][0];
1986 sign[triangle_counter] = s/(fabs(s));
1987 }
1988 else
1989 {
1990 UG_LOG("triangle mid edge with no corner node \n ");
1991 continue; //oder Fehler bei deg case
1992 }
1993 corneredge[triangle_counter] = edge;
1994 edgenum[triangle_counter] = j;
1995
1996 Face *nbfaces[2];
1997 if(GetAssociatedFaces(nbfaces,*pMG,edge,2)!=2)
1998 UG_THROW("FractDimadapt:tri_to_quad: edge has more than two faces\n");
1999
2000 int equal[2];
2001 for(size_t j=0; j< 2; j++)
2002 {
2003 equal[j]=1;
2004 for(size_t k = 0; k < nbfaces[j]->num_vertices(); k++)
2005 if(nbfaces[j]->vertex(k) != elem->vertex(k))
2006 {
2007 k = nbfaces[j]->num_vertices();
2008 equal[j] = 0;
2009 }
2010 }
2011 if(equal[0]==0 && equal[1]==0)
2012 UG_THROW("FractDimadapt:tri_to_quad: no elem found\n");
2013 for(size_t j=0; j< 2; j++)
2014 if(equal[j]==1)
2015 cornerface[triangle_counter] = nbfaces[j];
2016
2017 //list corners for new quadrilateral
2018 size_t count = 0;
2019 for(size_t k=0; k< elem->num_vertices(); k++)
2020 {
2021 vrtlist[triangle_counter][count+k] = elem->vertex(k);
2022 if(k==edgenum[triangle_counter])
2023 {
2024 count=1;
2025 vrtlist[triangle_counter][k+count] = NULL; //to be set later (newvrt)
2026 }
2027 }
2028
2029 triangle_counter++;
2030 if(triangle_counter>(2*max_number_deg_quadris))
2031 UG_THROW ("FractDimadapt:tri_to_quad: too many corner triangles");
2032 }
2033 }
2034 }
2035 }
2036
2037 //find corresponding pairs. Two triangles at each end.
2038 for (size_t i = 0; i < triangle_counter; i++)
2039 {
2040 for (size_t j = 0; j < triangle_counter; j++)
2041 {
2042 if(i==j)
2043 continue;
2044 if(cornervrt[i] == cornervrt[j])
2045 partner[i]=j;
2046 }
2047 }
2048
2049 //insert new vertices, edges and elems.
2050 //correct child structure and erase old parts
2051 int new_count = 0;
2052 for (size_t i = 0; i < triangle_counter; i++)
2053 {
2054 if(partner[i]<i)
2055 continue;
2056
2057 //special treatment for baselevel
2058 //as there are no parents here, subdomain info needs to be set
2059 if(lev == 0)
2060 {
2061 pMG->enable_hierarchical_insertion(false); //use only for base level! to set subset info for new vertices...
2062
2063 //insert vrt
2064 Vertex *newvrt = *pMG->create<RegularVertex>(corneredge[i]);
2065 if(m_shift == true)
2066 {
2067 //Todo SHIFT Debug
2068 number debug_shift = 1e-10;
2069
2070 aaPos[newvrt][0] = aaPos[cornervrt[i]][0] + sign[i]*debug_shift;
2071 aaPos[newvrt][1] = aaPos[cornervrt[i]][1];
2072 }
2073 else
2074 {
2075 MathVector<dim> tangential;
2076 tangential[0]= m_fractNormal[1];
2077 tangential[1]= -m_fractNormal[0];
2078 number step_x = fabs(aaPos[corneredge[i]->vertex(0)][0] - aaPos[corneredge[i]->vertex(1)][0]);
2079 number step_y= fabs(aaPos[corneredge[i]->vertex(0)][1] - aaPos[corneredge[i]->vertex(1)][1]);
2080 for(int l=0; l<m_NumberLevels; l++)
2081 {
2082 step_x /= 2;
2083 step_y /= 2;
2084 }
2085 step_x /= 5;
2086 step_y /= 5;
2087 aaPos[newvrt][0] = aaPos[cornervrt[i]][0] + fabs(tangential[0]) * sign[i] * step_x;
2088 aaPos[newvrt][1] = aaPos[cornervrt[i]][1] + fabs(tangential[1]) * sign[i] * step_y;
2089 }
2090
2091 new_vrt_father[new_count] = newvrt;
2092 //UG_LOG("new vrt "<<aaPos[newvrt] <<" \n ");
2093
2094 //save new vert and corner vert to assign c and p values later (after vector has new length)
2095 vert_pairs[vert_count][0] = newvrt;
2096 vert_pairs[vert_count][1] = cornervrt[i];
2097 vert_count++;
2098
2099 //insert corresponding edges
2100 Edge *newedge1 = *pMG->create<RegularEdge>(EdgeDescriptor(corneredge[i]->vertex(0),newvrt),corneredge[i]);
2101 Edge *newedge2 = *pMG->create<RegularEdge>(EdgeDescriptor(newvrt,corneredge[i]->vertex(1)),corneredge[i]);
2102
2104
2105 Edge *newparent;
2106 if(corneredge[i]->vertex(0)==cornervrt[i])
2107 {
2108 newparent = newedge2;
2109 new_fulledge_father[new_count] = newedge2;
2110 new_degedge_father[new_count] = newedge1;
2111 }
2112 else if(corneredge[i]->vertex(1)==cornervrt[i])
2113 {
2114 newparent = newedge1;
2115 new_fulledge_father[new_count] = newedge1;
2116 new_degedge_father[new_count] = newedge2;
2117 }
2118 else
2119 UG_THROW("FractDimadapt:tri_to_quad: some error in collected data\n");
2120
2121 //set new parents of child_edges and child_vertices
2122 for(size_t j = 0; j < pMG->num_child_edges(corneredge[i]); j++)
2123 pMG->associate_parent(pMG->get_child_edge(corneredge[i],j),newparent);
2124 for(size_t j = 0; j < pMG->num_child_vertices(corneredge[i]); j++)
2125 pMG->associate_parent(pMG->get_child_vertex(corneredge[i]),newparent);
2126
2127 //add newrt to list corners for new quadrilaterals.
2128 vrtlist[i][edgenum[i]+1] = newvrt;
2129 vrtlist[partner[i]][edgenum[partner[i]]+1] = newvrt;
2130
2131// UG_LOG("vrtlist " <<aaPos[vrtlist[i][0]]<<" "<<aaPos[vrtlist[i][1]]<<" "
2132// <<aaPos[vrtlist[i][2]]<<" "<<aaPos[vrtlist[i][3]]<<"\n ");
2133// UG_LOG("vrtlist " <<aaPos[vrtlist[partner[i]][0]]<<" "<<aaPos[vrtlist[partner[i]][1]]<<" "
2134// <<aaPos[vrtlist[partner[i]][2]]<<" "<<aaPos[vrtlist[partner[i]][3]]<<"\n ");
2135
2136 Face* face = NULL;
2137 //insert new elements
2138 //set subdoms
2139 // set parents of children of old elements
2140 Face* Fchildren_list[4]; //max_num_children macro rausfinden
2141 Edge* Echildren_list[2];
2142 size_t num_children = 0;
2143
2144 face = *pMG->create<Quadrilateral>(QuadrilateralDescriptor(vrtlist[i][0],vrtlist[i][1],
2145 vrtlist[i][2],vrtlist[i][3]));
2146 m_spSH->assign_subset(face, si);
2147
2148 num_children = pMG->num_child_faces(cornerface[i]);
2149 for(size_t k = 0; k < num_children; k++)
2150 Fchildren_list[k] = pMG->get_child_face(cornerface[i],k);
2151 for(size_t k = 0; k < num_children; k++)
2152 pMG->associate_parent(Fchildren_list[k],face);
2153
2154 num_children = pMG->num_child_edges(cornerface[i]);
2155 for(size_t k = 0; k < num_children; k++)
2156 Echildren_list[k] = pMG->get_child_edge(cornerface[i],k);
2157 for(size_t k = 0; k < num_children; k++)
2158 pMG->associate_parent(Echildren_list[k],face);
2159
2160 new_face1_father[new_count] = face;
2161
2162 face = *pMG->create<Quadrilateral>(QuadrilateralDescriptor(vrtlist[partner[i]][0],vrtlist[partner[i]][1],
2163 vrtlist[partner[i]][2],vrtlist[partner[i]][3]));
2164 m_spSH->assign_subset(face, si);
2165
2166 num_children = pMG->num_child_faces(cornerface[partner[i]]);
2167 for(size_t k = 0; k < num_children; k++)
2168 Fchildren_list[k] = pMG->get_child_face(cornerface[partner[i]],k);
2169 for(size_t k = 0; k < num_children; k++)
2170 pMG->associate_parent(Fchildren_list[k],face);
2171
2172 num_children = pMG->num_child_edges(cornerface[partner[i]]);
2173 for(size_t k = 0; k < num_children; k++)
2174 Echildren_list[k] = pMG->get_child_edge(cornerface[partner[i]],k);
2175 for(size_t k = 0; k < num_children; k++)
2176 pMG->associate_parent(Echildren_list[k],face);
2177
2178 new_count++;
2179 number_new_vrts++;
2180
2181 //erase old edge and therefore old triangles
2182 pMG->erase(corneredge[i]);
2183 }
2184 else //lev >0
2185 {
2186 //UG_LOG("lev "<<lev<<"\n");
2187 //get parent elem
2188 Face* parent1 = dynamic_cast<Face*>(pMG->get_parent(cornerface[i]));
2189 Face* parent2 = dynamic_cast<Face*>(pMG->get_parent(cornerface[partner[i]]));
2190
2191 //find out which saved new_vrt is the parent of the vrt to be inserted
2192 //by comparing the parent face with the saved face
2193 size_t this_id = max_number_deg_quadris+10;
2194 for(size_t k = 0; k < number_new_vrts; k++)
2195 {
2196 if(parent1 == new_face1_father[k] || parent2 == new_face1_father[k])
2197 this_id = k;
2198 }
2199 if(this_id == max_number_deg_quadris+10)
2200 UG_THROW("FractDimadapt:tri_to_quad: parent not found in list (lev "<<lev<<")\n");
2201
2202// //insert vrt as child of the one on the coarser lev
2203 Vertex *newvrt = *pMG->create<RegularVertex>(new_vrt_father[this_id]);
2204 aaPos[newvrt][0] = aaPos[new_vrt_father[this_id]][0];
2205 aaPos[newvrt][1] = aaPos[new_vrt_father[this_id]][1];
2206
2207 //save new vert and corner vert to assign c and p values later (after vector has new length)
2208 vert_pairs[vert_count][0] = newvrt;
2209 vert_pairs[vert_count][1] = cornervrt[i];
2210 vert_count++;
2211
2212 new_vrt_father[new_count] = newvrt;
2213 //UG_LOG("lev "<<lev<<" new vrt "<<aaPos[newvrt] <<" \n ");
2214
2215 //insert corresponding edges
2216 Edge *newdegedge = NULL;
2217 Edge *newfulledge = NULL;
2218
2219 if(corneredge[i]->vertex(0)==cornervrt[i])
2220 {
2221 newdegedge = *pMG->create<RegularEdge>(EdgeDescriptor(corneredge[i]->vertex(0),newvrt),new_degedge_father[this_id]);
2222 newfulledge = *pMG->create<RegularEdge>(EdgeDescriptor(newvrt,corneredge[i]->vertex(1)),new_fulledge_father[this_id]);
2223 }
2224 else if(corneredge[i]->vertex(1)==cornervrt[i])
2225 {
2226 newfulledge = *pMG->create<RegularEdge>(EdgeDescriptor(corneredge[i]->vertex(0),newvrt),new_fulledge_father[this_id]);
2227 newdegedge = *pMG->create<RegularEdge>(EdgeDescriptor(newvrt,corneredge[i]->vertex(1)),new_degedge_father[this_id]);
2228 }
2229 else
2230 UG_THROW("FractDimadapt:tri_to_quad: some error in collected data\n");
2231
2232 new_fulledge_father[new_count] = newfulledge;
2233 new_degedge_father[new_count] = newdegedge;
2234
2235 //set new parents of children
2236 for(size_t j = 0; j < pMG->num_child_edges(corneredge[i]); j++)
2237 pMG->associate_parent(pMG->get_child_edge(corneredge[i],j),newfulledge);
2238 for(size_t j = 0; j < pMG->num_child_vertices(corneredge[i]); j++)
2239 pMG->associate_parent(pMG->get_child_vertex(corneredge[i]),newfulledge);
2240
2241 //add newrt to list corners for new quadrilaterals.
2242 vrtlist[i][edgenum[i]+1] = newvrt;
2243 vrtlist[partner[i]][edgenum[partner[i]]+1] = newvrt;
2244
2245// UG_LOG("vrtlist " <<aaPos[vrtlist[i][0]]<<" "<<aaPos[vrtlist[i][1]]<<" "
2246// <<aaPos[vrtlist[i][2]]<<" "<<aaPos[vrtlist[i][3]]<<"\n ");
2247// UG_LOG("vrtlist " <<aaPos[vrtlist[partner[i]][0]]<<" "<<aaPos[vrtlist[partner[i]][1]]<<" "
2248// <<aaPos[vrtlist[partner[i]][2]]<<" "<<aaPos[vrtlist[partner[i]][3]]<<"\n ");
2249
2250 //insert new elements
2251 // and set parents of children of old elements
2252 Face* face = NULL;
2253 Face* Fchildren_list[4]; //max_num_children macro rausfinden
2254 Edge* Echildren_list[2];
2255 size_t num_children = 0;
2256
2257 face = *pMG->create<Quadrilateral>(QuadrilateralDescriptor(vrtlist[i][0],vrtlist[i][1],
2258 vrtlist[i][2],vrtlist[i][3]),parent1);
2259
2260 num_children = pMG->num_child_faces(cornerface[i]);
2261 for(size_t k = 0; k < num_children; k++)
2262 Fchildren_list[k] = pMG->get_child_face(cornerface[i],k);
2263 for(size_t k = 0; k < num_children; k++)
2264 pMG->associate_parent(Fchildren_list[k],face);
2265
2266 num_children = pMG->num_child_edges(cornerface[i]);
2267 for(size_t k = 0; k < num_children; k++)
2268 Echildren_list[k] = pMG->get_child_edge(cornerface[i],k);
2269 for(size_t k = 0; k < num_children; k++)
2270 pMG->associate_parent(Echildren_list[k],face);
2271 new_face1_father[new_count] = face;
2272
2273
2274 face = *pMG->create<Quadrilateral>(QuadrilateralDescriptor(vrtlist[partner[i]][0],vrtlist[partner[i]][1],
2275 vrtlist[partner[i]][2],vrtlist[partner[i]][3]),parent2);
2276
2277 num_children = pMG->num_child_faces(cornerface[partner[i]]);
2278 for(size_t k = 0; k < num_children; k++)
2279 Fchildren_list[k] = pMG->get_child_face(cornerface[partner[i]],k);
2280 for(size_t k = 0; k < num_children; k++)
2281 pMG->associate_parent(Fchildren_list[k],face);
2282
2283 num_children = pMG->num_child_edges(cornerface[partner[i]]);
2284 for(size_t k = 0; k < num_children; k++)
2285 Echildren_list[k] = pMG->get_child_edge(cornerface[partner[i]],k);
2286 for(size_t k = 0; k < num_children; k++)
2287 pMG->associate_parent(Echildren_list[k],face);
2288
2289 new_count++;
2290
2291 //erase old edge and therefore old triangles
2292 pMG->erase(corneredge[i]);
2293 }
2294// SubsetHandler &sh = *m_spSH.get();
2295// SaveGridHierarchyTransformed(*pMG, m_spSH.get(), "hallo.ugx", 1);
2296 }
2297 }
2298 }
2299
2300 //debug
2301// for (int lev = 0; lev < m_NumberLevels; lev++)
2302// {
2303// for (int k = 0; k < NumberFractNodes[lev]; k++)
2304// {
2305// MathVector<dim> newcoord;
2306// MathVector<dim> shift = vert_shift(FractNode[lev][k][1]);
2307// VecAdd(newcoord,aaPos[FractNode[lev][k][1]],shift);
2308// aaPos[FractNode[lev][k][1]] = newcoord;
2309// shift = vert_shift(FractNode[lev][k][2]);
2310// VecAdd(newcoord,aaPos[FractNode[lev][k][2]],shift);
2311// aaPos[FractNode[lev][k][2]] = newcoord;
2312// }
2313// }
2314
2315
2316
2317 //update fract manager
2318 fractManager->close();
2319
2320 //end of grid adaption noticed by messenger
2322
2323
2324 //assign c and p values at new node (copy those of cornernode)
2325 for(size_t i=vert_count-2; i < vert_count; i++)
2326 {
2327 number c,p;
2328 u.dof_indices(vert_pairs[i][1], 0, multInd);
2329 c = DoFRef(u,multInd[0]);
2330 u.dof_indices(vert_pairs[i][0], 0, multInd);
2331 DoFRef(u,multInd[0]) = c;
2332
2333 u.dof_indices(vert_pairs[i][1], 1, multInd);
2334 p = DoFRef(u,multInd[0]);
2335 u.dof_indices(vert_pairs[i][0], 1, multInd);
2336 DoFRef(u,multInd[0]) = p;
2337 }
2338
2339}
2340
2346template <typename TDomain,typename TAlgebra>
2349)
2350{
2351 UG_LOG("convert_quad_to_tri \n");
2352
2353 // create Multiindex
2354 std::vector<DoFIndex> multInd;
2355
2356 typedef typename geometry_traits<element_type>::const_iterator t_elem_iter;
2357
2358 MultiGrid * pMG = (MultiGrid *) (m_spSH->multi_grid ());
2359
2360 typename Grid::traits<Edge>::secure_container edge_list;
2361
2362
2363 typedef typename domain_type::position_attachment_type pos_att_type;
2364 pos_att_type aPos = m_dom->position_attachment();
2366 aaPos.access (*pMG, aPos);
2367
2368
2369 //begin of grid adaption noticed by messenger
2371
2372 size_t num_vert = 2 * m_NumberLevels;
2373 std::vector<Vertex*> vertex_to_erase(num_vert);
2374 size_t vert_count = 0;
2375
2376 for (int lev = 0; lev < m_NumberLevels; lev++)
2377 {
2378 size_t triangle_counter = 0;
2379
2380 Edge * corneredge[4];
2381 Edge * midedge[4];
2382 Face* cornerface[4];
2383
2384 Vertex * cornervrt[4];
2385 Vertex * triquadvrt[4];
2386 Vertex * vrtlist[4][3];
2387 size_t partner[4];
2388 size_t edge_num[4]; //corneredge->vertex(edge_num) is cornervert
2389
2390 for (size_t h = 0; h < m_fractSsGrp.size (); h++)
2391 {
2392 int si = m_fractSsGrp [h];
2393
2394 //find the end quadrilaterals.
2395 //store all relevant information in arrays
2396 for (t_elem_iter iElem = m_spSH->template begin<element_type> (si, lev);
2397 iElem != m_spSH->template end<element_type> (si, lev); ++iElem)
2398 {
2399 element_type * elem = *iElem;
2400 for (size_t j = 0; j < elem->num_vertices (); j++)
2401 {
2402 Vertex * vert = elem->vertex(j);
2403 //find the corner-quadri
2404 if(vert_mark(vert) == F_CORNER)
2405 {
2406 if(elem->num_vertices ()!=4)
2407 UG_THROW("FractDimadapt:quad_to_tri: corner elem is no quadrilateral\n");
2408
2409 //save vertices and edges
2410 cornervrt[triangle_counter] = vert;
2411
2412 pMG->associated_elements_sorted (edge_list, elem);
2413 for (size_t i = 0; i < edge_list.size (); i++)
2414 {
2415 Edge * edge = edge_list [i];
2416 if(vert_mark(edge->vertex(0)) == F_MID)
2417 {
2418 if(vert_mark(edge->vertex(1)) == F_MID)
2419 {
2420 midedge[triangle_counter] = edge;
2421 }
2422 else if(vert_mark(edge->vertex(1)) == F_CORNER)
2423 {
2424 corneredge[triangle_counter] = edge;
2425 triquadvrt[triangle_counter] = edge->vertex(0);
2426 edge_num[triangle_counter] = 1;
2427 }
2428 }
2429 else if(vert_mark(edge->vertex(0)) == F_CORNER)
2430 {
2431 if(vert_mark(edge->vertex(1)) == F_MID)
2432 {
2433 corneredge[triangle_counter] = edge;
2434 triquadvrt[triangle_counter] = edge->vertex(1);
2435 edge_num[triangle_counter] = 0;
2436 }
2437 }
2438 }
2439
2440 //list of vertices for new element
2441 size_t list_num = 0;
2442 for (size_t i = 0; i < elem->num_vertices (); i++)
2443 {
2444 Vertex * covert = elem->vertex(i);
2445 if(covert != triquadvrt[triangle_counter])
2446 {
2447 vrtlist[triangle_counter][list_num] = covert;
2448 list_num++;
2449 }
2450 }
2451
2452 //save the face
2453 Face *nbfaces[2];
2454 if(GetAssociatedFaces(nbfaces,*pMG,corneredge[triangle_counter],2)!=2)
2455 UG_THROW("FractDimadapt:quad_to_tri: edge has more than two faces\n");
2456 int equal[2];
2457 for(size_t i=0; i< 2; i++)
2458 {
2459 equal[i]=1;
2460 for(size_t k = 0; k < nbfaces[i]->num_vertices(); k++)
2461 if(nbfaces[i]->vertex(k) != elem->vertex(k))
2462 {
2463 k = nbfaces[i]->num_vertices();
2464 equal[i] = 0;
2465 }
2466 }
2467 if(equal[0]==0 && equal[1]==0)
2468 UG_THROW("FractDimadapt:quad_to_tri: no elem found\n");
2469 for(size_t k=0; k < 2; k++)
2470 if(equal[k]==1)
2471 cornerface[triangle_counter] = nbfaces[k];
2472
2473 triangle_counter++;
2474 j=elem->num_vertices ();
2475 }
2476 }
2477 }
2478
2479 //find partner
2480 for (size_t i = 0; i < triangle_counter; i++)
2481 {
2482 for (size_t j = 0; j < triangle_counter; j++)
2483 {
2484 if(i==j)
2485 continue;
2486 if(cornervrt[i] == cornervrt[j])
2487 partner[i]=j;
2488 }
2489 }
2490
2491 //create new elems
2492 //reset parent child connections
2493 for (size_t i = 0; i < triangle_counter; i++)
2494 {
2495 if(partner[i]<i)
2496 continue;
2497
2498 //store vert in array (erased later after parent-child-connections are all clear)
2499 vertex_to_erase[vert_count] = triquadvrt[i];
2500 vert_count++;
2501
2502 //insert new edges
2503 Edge *newedge = NULL;
2504 if(lev==0)
2505 {
2506 pMG->enable_hierarchical_insertion(false); //use only for base level! to set subset info for new vertices...
2507 if(edge_num[i]==0)
2508 newedge = *pMG->create<RegularEdge>(EdgeDescriptor(cornervrt[i],midedge[i]->vertex(1)),midedge[i]);
2509 else
2510 newedge = *pMG->create<RegularEdge>(EdgeDescriptor(midedge[i]->vertex(0),cornervrt[i]),midedge[i]);
2512 }
2513 else
2514 {
2515 Edge * parentedge = dynamic_cast<Edge*>(pMG->get_parent(midedge[i]));
2516 if(edge_num[i]==0)
2517 newedge = *pMG->create<RegularEdge>(EdgeDescriptor(cornervrt[i],midedge[i]->vertex(1)),parentedge);
2518 else
2519 newedge = *pMG->create<RegularEdge>(EdgeDescriptor(midedge[i]->vertex(0),cornervrt[i]),parentedge);
2520 }
2521 //set new parents of child_edges and child_vertices
2522 for(size_t j = 0; j < pMG->num_child_edges(midedge[i]); j++)
2523 pMG->associate_parent(pMG->get_child_edge(midedge[i],j),newedge);
2524 for(size_t j = 0; j < pMG->num_child_vertices(midedge[i]); j++)
2525 pMG->associate_parent(pMG->get_child_vertex(midedge[i]),newedge);
2526
2527// UG_LOG("vrtlist " <<aaPos[vrtlist[i][0]]<<" "<<aaPos[vrtlist[i][1]]<<" "
2528// <<aaPos[vrtlist[i][2]]<<"\n ");
2529// UG_LOG("vrtlist " <<aaPos[vrtlist[partner[i]][0]]<<" "<<aaPos[vrtlist[partner[i]][1]]<<" "
2530// <<aaPos[vrtlist[partner[i]][2]]<<"\n ");
2531
2532 //insert new elements
2533 // and set parents of children of old elements
2534 Face* face = NULL;
2535 Face* Fchildren_list[4]; //max_num_children macro rausfinden
2536 Edge* Echildren_list[2];
2537 size_t num_children = 0;
2538
2539 //first elem
2540 if(lev==0)
2541 {
2542 face = *pMG->create<Triangle>(TriangleDescriptor(vrtlist[i][0],vrtlist[i][1],
2543 vrtlist[i][2]));
2544 m_spSH->assign_subset(face, si);
2545 }
2546 else
2547 {
2548 Face * parentface = dynamic_cast<Face*>(pMG->get_parent(cornerface[i]));
2549 face = *pMG->create<Triangle>(TriangleDescriptor(vrtlist[i][0],vrtlist[i][1],
2550 vrtlist[i][2]),parentface);
2551 }
2552 num_children = pMG->num_child_faces(cornerface[i]);
2553 for(size_t k = 0; k < num_children; k++)
2554 Fchildren_list[k] = pMG->get_child_face(cornerface[i],k);
2555 for(size_t k = 0; k < num_children; k++)
2556 pMG->associate_parent(Fchildren_list[k],face);
2557
2558 num_children = pMG->num_child_edges(cornerface[i]);
2559 for(size_t k = 0; k < num_children; k++)
2560 Echildren_list[k] = pMG->get_child_edge(cornerface[i],k);
2561 for(size_t k = 0; k < num_children; k++)
2562 pMG->associate_parent(Echildren_list[k],face);
2563
2564 //second elem
2565 if(lev==0)
2566 {
2567 face = *pMG->create<Triangle>(TriangleDescriptor(vrtlist[partner[i]][0],vrtlist[partner[i]][1],
2568 vrtlist[partner[i]][2]));
2569 m_spSH->assign_subset(face, si);
2570 }
2571 else
2572 {
2573 Face * parentface = dynamic_cast<Face*>(pMG->get_parent(cornerface[partner[i]]));
2574 face = *pMG->create<Triangle>(TriangleDescriptor(vrtlist[partner[i]][0],vrtlist[partner[i]][1],
2575 vrtlist[partner[i]][2]),parentface);
2576 }
2577 num_children = pMG->num_child_faces(cornerface[partner[i]]);
2578 for(size_t k = 0; k < num_children; k++)
2579 Fchildren_list[k] = pMG->get_child_face(cornerface[partner[i]],k);
2580 for(size_t k = 0; k < num_children; k++)
2581 pMG->associate_parent(Fchildren_list[k],face);
2582
2583 num_children = pMG->num_child_edges(cornerface[partner[i]]);
2584 for(size_t k = 0; k < num_children; k++)
2585 Echildren_list[k] = pMG->get_child_edge(cornerface[partner[i]],k);
2586 for(size_t k = 0; k < num_children; k++)
2587 pMG->associate_parent(Echildren_list[k],face);
2588 }
2589 }
2590 }
2591
2592 //erase vrt and therefore corresponding edges/elems
2593 for (size_t i = 0; i < vert_count; i++)
2594 {
2595 pMG->erase(vertex_to_erase[i]);
2596 }
2597
2598
2599 //update fract manager
2600 fractManager->close();
2601
2602 //end of grid adaption noticed by messenger
2604}
2605
2606
2607
2608} // namespace d3f
2609} // end namespace ug
2610
2611/* End of File */
parameterString p
Definition Biogas.lua:1
parameterString s
Definition Biogas.lua:2
bool invalid() const
void remove(const char *ss_names)
void add(const char *ss_names)
grid_dim_traits< dim >::side_type side_type
void get_layer_sides(element_type *elem, size_t &num_fract_co, side_type *&inner_side, size_t &inner_side_idx, size_t inner_side_corners[], side_type *&outer_side, size_t &outer_side_idx, size_t outer_side_corners[], size_t ass_co[]=NULL)
const MathVector< dim > * local_grad_vector() const
const MathMatrix< worldDim, dim > & JTInv() const
const MathVector< dim > & local_ip() const
number shape(size_t sh) const
const MathVector< worldDim > & global_grad(size_t sh) const
const SCVF & scvf(size_t i) const
size_t num_sh() const
const MathVector< worldDim > * corners() const
void update(GridObject *elem, const MathVector< worldDim > *vCornerCoords, const ISubsetHandler *ish=NULL)
size_t num_scvf() const
virtual Vertex * vertex(size_t index) const
virtual size_t num_vertices() const
virtual size_t num_vertices() const
virtual Vertex * vertex(size_t index) const
static TGeom & get()
bool access(Grid &grid, TAttachment &a)
SPMessageHub message_hub()
void associated_elements_sorted(traits< Edge >::secure_container &elemsOut, TElem *e)
void erase(const GeomObjIter &iterBegin, const GeomObjIter &iterEnd)
bool adaption_ends() const
GridMessageDistributionType msg() const
virtual bool is_constrained() const
void associate_parent(TElem *elem, GridObject *parent)
size_t num_levels() const
size_t num_child_vertices(TElem *elem) const
size_t num_child_faces(TElem *elem) const
GridObject * get_parent(Edge *o) const
Vertex * get_child_vertex(TElem *elem) const
geometry_traits< TGeomObj >::iterator create(const typename geometry_traits< TGeomObj >::Descriptor &descriptor, GridObject *pParent=NULL)
Edge * get_child_edge(TElem *elem, size_t ind) const
void enable_hierarchical_insertion(bool bEnable)
Face * get_child_face(TElem *elem, size_t ind) const
size_t num_child_edges(TElem *elem) const
size_t size() const
Definition fract_dimadapt.h:34
FractDimadapt(SmartPtr< domain_type > domain, const char *ss_name, const std::vector< number > normal, number aperture, bool shift)
Constructor.
Definition fract_dimadapt_impl.h:36
void transfer_full_to_low(TGridFunction &u)
transfer of solution
Definition fract_dimadapt_impl.h:1116
void mark_vertices()
Marks the inner fracture vertices.
Definition fract_dimadapt_impl.h:144
void convert_end_quadris_to_triangles(DegeneratedLayerManager< TDomain::dim > *fractManager)
this function converts degenerated end quadrilaterals to traingles
Definition fract_dimadapt_impl.h:2347
void convert_end_triangles_to_quadris(TGridFunction &u, DegeneratedLayerManager< TDomain::dim > *fractManager)
Definition fract_dimadapt_impl.h:1904
number evaluate_criterion(TGridFunction &u, DegeneratedLayerManager< TDomain::dim > *fractManager, number omega_theta, number time)
Computes the criterion (Dissertation Stichel Section 7.2.1)
Definition fract_dimadapt_impl.h:715
void grid_distribution_callback(const GridMessage_Distribution &msg)
Called when a grid has been distributed between different processes.
Definition fract_dimadapt_impl.h:132
void get_ave_val(const std::vector< number > eval_point, TGridFunction &u, number time)
Computes average over fracture width at given point.
Definition fract_dimadapt_impl.h:542
void transfer_low_to_full(TGridFunction &u)
transfer of solution
Definition fract_dimadapt_impl.h:1309
void grid_adaption_callback(const GridMessage_Adaption &msg)
Called when a grid adaption has been performed.
Definition fract_dimadapt_impl.h:119
domain_traits< dim >::grid_base_object element_type
base grid element object type
Definition fract_dimadapt.h:56
void grid_transfer_full_to_low()
grid transfer
Definition fract_dimadapt_impl.h:1442
domain_type::position_accessor_type position_accessor_type
get position accessor
Definition fract_dimadapt.h:65
void viscosity_func(number c, number &mu, number &d_mu)
Calculates the viscosity and its derivative dependent on mass fraction.
Definition fract_dimadapt_impl.h:519
void calculate_interpolation(double bnd[2][2], double mid[2], MathVector< dim > bndpoint[2], number param[2][3])
Help function for transfer_low_to_full (calculate quadratic behaviour of unknowns in fracture)
Definition fract_dimadapt_impl.h:1197
void density_func(number c, number &rho, number &d_rho)
Calculates the density and its derivative dependent on mass fraction.
Definition fract_dimadapt_impl.h:498
void check_transfer(TGridFunction &u, DegeneratedLayerManager< TDomain::dim > *fractManager, number omega_theta, number delta, number time)
Checks if the criterion suggests the change of the grid.
Definition fract_dimadapt_impl.h:1039
void grid_transfer_low_to_full()
grid transfer
Definition fract_dimadapt_impl.h:1709
virtual ~FractDimadapt()
Destructor.
Definition fract_dimadapt_impl.h:104
UG_API TVertexPositionAttachmentAccessor::ValueType CalculateCenter(const Edge *e, TVertexPositionAttachmentAccessor &aaPosVRT)
int GetAssociatedFaces(Face **facesOut, Grid &grid, Edge *e, int maxNumFaces)
#define UG_CATCH_THROW(msg)
#define UG_THROW(msg)
#define UG_LOG(msg)
#define UG_COND_THROW(cond, msg)
double number
vector_t::value_type VecLength(const vector_t &v)
void VecScaleAppend(vector_t &vOut, typename vector_t::value_type s1, const vector_t &v1)
void VecAdd(vector_t &vOut, const vector_t &v, typename vector_t::value_type s)
vector_t::value_type VecDistance(const vector_t &v1, const vector_t &v2)
void VecSubtract(vector_t &vOut, const vector_t &v, typename vector_t::value_type s)
void VecScale(vector_t &vOut, const vector_t &v, typename vector_t::value_type s)
vector_t::value_type VecDot(const vector_t &v1, const vector_t &v2)
const number & DoFRef(const TMatrix &mat, const DoFIndex &iInd, const DoFIndex &jInd)
GMDT_DISTRIBUTION_STOPS
GMAT_HNODE_ADAPTION_ENDS
GMAT_HNODE_ADAPTION_BEGINS
void vorticity(TGridFunction &vort, TGridFunction &u)
Definition navier_stokes_tools.h:528
int DimensionOfSubset(const ISubsetHandler &sh, int si)
void VecSet(vector_t &dest, number alpha, const std::vector< size_t > vIndex)
bool resize(size_t newRows, size_t newCols)