OOFEM  2.4
OOFEM.org - Object Oriented Finite Element Solver
leplic.C
Go to the documentation of this file.
1 /*
2  *
3  * ##### ##### ###### ###### ### ###
4  * ## ## ## ## ## ## ## ### ##
5  * ## ## ## ## #### #### ## # ##
6  * ## ## ## ## ## ## ## ##
7  * ## ## ## ## ## ## ## ##
8  * ##### ##### ## ###### ## ##
9  *
10  *
11  * OOFEM : Object Oriented Finite Element Code
12  *
13  * Copyright (C) 1993 - 2013 Borek Patzak
14  *
15  *
16  *
17  * Czech Technical University, Faculty of Civil Engineering,
18  * Department of Structural Mechanics, 166 29 Prague, Czech Republic
19  *
20  * This library is free software; you can redistribute it and/or
21  * modify it under the terms of the GNU Lesser General Public
22  * License as published by the Free Software Foundation; either
23  * version 2.1 of the License, or (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28  * Lesser General Public License for more details.
29  *
30  * You should have received a copy of the GNU Lesser General Public
31  * License along with this library; if not, write to the Free Software
32  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33  */
34 
35 #include "leplic.h"
36 #include "mathfem.h"
37 #include "timestep.h"
38 #include "geotoolbox.h"
39 #include "node.h"
40 #include "connectivitytable.h"
41 #include "datastream.h"
42 #include "spatiallocalizer.h"
43 #include "contextioerr.h"
44 #include "element.h"
45 #include "dynamicinputrecord.h"
46 #include "engngm.h"
47 
48 namespace oofem {
49 #define LEPLIC_ZERO_VOF 1.e-8
50 #define LEPLIC_BRENT_EPS 1.e-8
51 
52 
53 bool
55 {
56  double fvk, fvi = this->giveTempVolumeFraction();
57  IntArray currCell(1), neighborList;
58  LEPlicElementInterface *ineghbrInterface;
59  Domain *domain = this->giveElement()->giveDomain();
60  ConnectivityTable *contable = domain->giveConnectivityTable();
61  if ( ( fvi > 0. ) && ( fvi <= 1.0 ) ) {
62  // potentially boundary cell
63  if ( ( fvi > 0. ) && ( fvi < 1.0 ) ) {
64  return true;
65  }
66 
67  currCell.at(1) = this->giveElement()->giveNumber();
68  contable->giveElementNeighbourList(neighborList, currCell);
69  // loop over neighbors to assemble normal equations
70  for ( int ineighbr: neighborList ) {
71  if ( ( ineghbrInterface =
72  static_cast< LEPlicElementInterface * >( domain->giveElement(ineighbr)->giveInterface(LEPlicElementInterfaceType) ) ) ) {
73  fvk = ineghbrInterface->giveTempVolumeFraction();
74  if ( fvk < 1.0 ) {
75  return true;
76  }
77  }
78  }
79  }
80 
81  return false;
82 }
83 
84 
87 {
88  contextIOResultType iores;
89 
90  // write a raw data
91  if ( !stream.write(vof) ) {
93  }
94 
95  if ( !stream.write(p) ) {
97  }
98 
99  if ( ( iores = normal.storeYourself(stream) ) != CIO_OK ) {
100  THROW_CIOERR(iores);
101  }
102 
103  return CIO_OK;
104 }
105 
108 {
109  contextIOResultType iores;
110 
111  // read raw data
112  if ( !stream.read(vof) ) {
114  }
115 
116  temp_vof = vof;
117  if ( !stream.read(p) ) {
119  }
120 
121  temp_p = p;
122  if ( ( iores = normal.restoreYourself(stream) ) != CIO_OK ) {
123  THROW_CIOERR(iores);
124  }
125 
127  return CIO_OK;
128 }
129 
130 
131 
132 
133 
134 void
136 {
138 #ifdef __OOFEG
139  //deleteLayerGraphics(OOFEG_DEBUG_LAYER);
141 #endif
142  this->doLagrangianPhase(tStep);
143  this->doInterfaceReconstruction(tStep, true, false);
144 #ifdef __OOFEG
145  //ESIEventLoop (YES, "doInterfaceReconstruction Finished; Press Ctrl-p to continue");
147 #endif
148  this->doInterfaceRemapping(tStep);
149  // here the new VOF values are determined, now we call doInterfaceReconstruction
150  // to reconstruct interface (normal, constant) on original grid
151  this->doInterfaceReconstruction(tStep, false, true);
152 #ifdef __OOFEG
153  ESIEventLoop( NO, const_cast< char * >("doInterfaceReconstruction Finished; Press Ctrl-p to continue") );
154  //ESIEventLoop (YES, "doInterfaceReconstruction Finished; Press Ctrl-p to continue");
155 #endif
156 }
157 
158 void
160 {
161  //Maps element nodes along trajectories using basic Runge-Kutta method (midpoint rule)
162  int i, ci, ndofman = domain->giveNumberOfDofManagers();
163  int nsd = 2;
164  double dt = tStep->giveTimeIncrement();
165  DofManager *dman;
166  Node *inode;
167  IntArray velocityMask;
168  FloatArray x, x2(nsd), v_t, v_tn1;
169  FloatMatrix t;
170 #if 1
171  EngngModel *emodel = domain->giveEngngModel();
172  int err;
173 #endif
174  velocityMask = {V_u, V_v};
175 
176  updated_XCoords.resize(ndofman);
177  updated_YCoords.resize(ndofman);
178 
179 
180  for ( i = 1; i <= ndofman; i++ ) {
181  dman = domain->giveDofManager(i);
182  inode = dynamic_cast< Node * >(dman);
183  // skip dofmanagers with no position information
184  if ( !inode ) {
185  continue;
186  }
187 
188  // get node coordinates
189  x = * ( inode->giveCoordinates() );
190  // get velocity field v(tn, x(tn)) for dof manager
191 
192 #if 1
193  /* Original version */
194  dman->giveUnknownVector( v_t, velocityMask, VM_Total, tStep->givePreviousStep() );
195  /* Modified version */
196  //dman->giveUnknownVector(v_t, velocityMask, VM_Total, tStep);
197 
198  // Original version
199  // compute updated position x(tn)+0.5*dt*v(tn,x(tn))
200  for ( ci = 1; ci <= nsd; ci++ ) {
201  x2.at(ci) = x.at(ci) + 0.5 *dt *v_t.at(ci);
202  }
203 
204  // compute interpolated velocity field at x2 [ v(tn+1, x(tn)+0.5*dt*v(tn,x(tn))) = v(tn+1, x2) ]
205 
206  FieldPtr vfield;
207  vfield = emodel->giveContext()->giveFieldManager()->giveField(FT_Velocity);
208  if ( vfield == NULL ) {
209  OOFEM_ERROR("Velocity field not available");
210  }
211 
212  err = vfield->evaluateAt(v_tn1, x2, VM_Total, tStep);
213  if ( err == 1 ) {
214  // point outside domain -> be explicit
215  v_tn1 = v_t;
216  } else if ( err != 0 ) {
217  OOFEM_ERROR("vfield->evaluateAt failed, error code %d", err);
218  }
219 
220  // compute final updated position
221  for ( ci = 1; ci <= nsd; ci++ ) {
222  x2.at(ci) = x.at(ci) + dt *v_tn1.at(ci);
223  }
224 
225 #else
226  // pure explicit version
227  dman->giveUnknownVector(v_t, velocityMask, VM_Total, tStep);
228 
229  for ( ci = 1; ci <= nsd; ci++ ) {
230  x2.at(ci) = x.at(ci) + dt *v_t.at(ci);
231  }
232 
233 #endif
234  // store updated node position
235  updated_XCoords.at(i) = x2.at(1);
236  updated_YCoords.at(i) = x2.at(2);
237  }
238 }
239 
240 void
242 {
243  /* Here volume materials are reconstructed on the new Lagrangian grid */
244 
245  int nelem = domain->giveNumberOfElements();
246  double p;
247 
248  FloatArray fvgrad(2);
249  LEPlicElementInterface *interface;
250 
251 
252  // loop over elements
253  for ( int ie = 1; ie <= nelem; ie++ ) {
254  /* STEP 1: first do DLS (Differential least square reconstruction) */
255  this->doCellDLS(fvgrad, ie, coord_upd, temp_vof);
256  /* STEP 2: Finding the line constant */
257  this->findCellLineConstant(p, fvgrad, ie, coord_upd, temp_vof);
258 
259  interface = static_cast< LEPlicElementInterface * >( domain->giveElement(ie)->giveInterface(LEPlicElementInterfaceType) );
260  interface->setTempLineConstant(p);
261  interface->setTempInterfaceNormal(fvgrad);
262  } // end loop over all elements
263 }
264 
265 
266 void
268 {
269  /*
270  * Final step: deposition of volume materials truncated on Lagrangian (updated)
271  * grid to the target grid, which is the original one in our Eulerian case.
272  */
273  int neighbrNum, nelem = domain->giveNumberOfElements();
274  double in_vof, total_volume = 0.0, in_vol;
275  IntArray neighbours, elNum(1);
277  Polygon matvolpoly, elemPoly;
278  Graph g;
279 
280  double matVol = 0.0, matVolSum = 0.0;
281 
282  LEPlicElementInterface *interface, *neghbrInterface;
283  // loop over elements
284  for ( int ie = 1; ie <= nelem; ie++ ) {
285  if ( ( interface = static_cast< LEPlicElementInterface * >( domain->giveElement(ie)->giveInterface(LEPlicElementInterfaceType) ) ) ) {
286  interface->setTempVolumeFraction(0.0);
287  }
288  }
289 
290  // loop over elements
291  for ( int ie = 1; ie <= nelem; ie++ ) {
292  //fprintf (stderr, "doInterfaceRemapping: processing elem %d\n", ie);
293 
294  // examine only neighbours -> this is the limit on time step
295  elNum.at(1) = ie;
296  domain->giveConnectivityTable()->giveElementNeighbourList(neighbours, elNum);
297  // form polygon of material volume on Lagrangian element
298  if ( ( interface = static_cast< LEPlicElementInterface * >( domain->giveElement(ie)->giveInterface(LEPlicElementInterfaceType) ) ) ) {
299  if ( interface->giveVolumeFraction() > LEPLIC_ZERO_VOF ) {
300  interface->giveTempInterfaceNormal(normal);
301  interface->formMaterialVolumePoly(matvolpoly, this, normal, interface->giveTempLineConstant(), true);
302  matVol = matvolpoly.computeVolume();
303 
304 #ifdef __OOFEG
305  //EASValsSetColor(::gc[OOFEG_DEBUG_LAYER].getElementColor());
306  //GraphicObj *go = matvolpoly.draw(::gc[OOFEG_DEBUG_LAYER],true);
307  //EVHiliteGraphics (myview, go);
308  //ESIEventLoop (YES, "Press Ctrl-p to continue");
309  //EVFastRedraw(myview);
310 #endif
311 
312 
313  try {
314  matVolSum = 0.0;
315  // loop over neighbours to truncate material volume on target (original) grid
316  for ( int in = 1; in <= neighbours.giveSize(); in++ ) {
317  neighbrNum = neighbours.at(in);
318  if ( ( neghbrInterface = static_cast< LEPlicElementInterface * >
319  ( domain->giveElement(neighbrNum)->giveInterface(LEPlicElementInterfaceType) ) ) ) {
320  in_vof = neghbrInterface->truncateMatVolume(matvolpoly, in_vol);
321  neghbrInterface->addTempVolumeFraction(in_vof);
322  total_volume += in_vol;
323  matVolSum += in_vol;
324  }
325  }
326  } catch(GT_Exception & c) {
327  c.print();
328 
329  neighbrNum = neighbours.at(1);
330  if ( ( neghbrInterface = static_cast< LEPlicElementInterface * >
331  ( domain->giveElement(neighbrNum)->giveInterface(LEPlicElementInterfaceType) ) ) ) {
332  in_vof = neghbrInterface->truncateMatVolume(matvolpoly, in_vol);
333  neghbrInterface->addTempVolumeFraction(in_vof);
334  }
335  }
336 
337 #ifdef __OOFEG
338  //ESIEventLoop (YES, "Step Finished; Press Ctrl-p to continue");
339 #endif
340  double err = fabs(matVol - matVolSum) / matVol;
341  if ( ( err > 1.e-12 ) && ( fabs(matVol - matVolSum) > 1.e-4 ) && ( matVol > 1.e-6 ) ) {
342  OOFEM_WARNING("volume inconsistency %5.2f%%\n\ttstep %d, element %d\n", err * 100, tStep->giveNumber(), ie);
343  }
344 
345 #if 0
346  if ( ( err > 2.e-3 ) && ( fabs(matVol - matVolSum) > 2.e-3 ) ) {
347  //debug
348 
349  #ifdef __OOFEG
350  //ESIEventLoop (YES, "Press Ctrl-p to continue");
352  EASValsSetColor( :: gc [ OOFEG_DEBUG_LAYER ].getElementColor() );
353  //GraphicObj *go = matvolpoly.draw(::gc[OOFEG_DEBUG_LAYER],true);
354  matvolpoly.draw(:: gc [ OOFEG_DEBUG_LAYER ], true);
355  //EVHiliteGraphics (myview, go);
356  //ESIEventLoop (YES, "Press Ctrl-p to continue");
358  #endif
359 
360  matVolSum = 0.0;
361  // loop over neighbours to truncate material volume on target (original) grid
362  for ( int in = 1; in <= neighbours.giveSize(); in++ ) {
363  neighbrNum = neighbours.at(in);
364  if ( neghbrInterface = static_cast< LEPlicElementInterface * >
365  ( domain->giveElement(neighbrNum)->giveInterface(LEPlicElementInterfaceType) ) ) {
366  in_vof = neghbrInterface->truncateMatVolume(matvolpoly, in_vol);
367  neghbrInterface->addTempVolumeFraction(in_vof);
368  total_volume += in_vol;
369  matVolSum += in_vol;
370  }
371  }
372 
373  matVolSum = 0.0;
374  // loop over neighbours to truncate material volume on target (original) grid
375  for ( int in = 1; in <= neighbours.giveSize(); in++ ) {
376  neighbrNum = neighbours.at(in);
377  if ( neghbrInterface = static_cast< LEPlicElementInterface * >
378  ( domain->giveElement(neighbrNum)->giveInterface(LEPlicElementInterfaceType) ) ) {
379  in_vof = neghbrInterface->truncateMatVolume(matvolpoly, in_vol);
380  neghbrInterface->addTempVolumeFraction(in_vof);
381  total_volume += in_vol;
382  matVolSum += in_vol;
383  }
384  }
385 
386  matVolSum = 0.0;
387  // loop over neighbours to truncate material volume on target (original) grid
388  for ( int in = 1; in <= neighbours.giveSize(); in++ ) {
389  neighbrNum = neighbours.at(in);
390  if ( neghbrInterface = static_cast< LEPlicElementInterface * >
391  ( domain->giveElement(neighbrNum)->giveInterface(LEPlicElementInterfaceType) ) ) {
392  in_vof = neghbrInterface->truncateMatVolume(matvolpoly, in_vol);
393  neghbrInterface->addTempVolumeFraction(in_vof);
394  total_volume += in_vol;
395  matVolSum += in_vol;
396  }
397  }
398 
399  /*
400  * ESIEventLoop (YES, "Press Ctrl-p to exit");
401  * ESIEventLoop (YES, "Press Ctrl-p to exit");
402  */
403  exit(1);
404  }
405 
406 #endif
407  }
408  } else {
409  OOFEM_ERROR("Element with no LEPlicInterface support encountered");
410  }
411  } // end loop over elements
412 
413  // loop over elements
414  for ( int ie = 1; ie <= nelem; ie++ ) {
415  if ( ( interface = static_cast< LEPlicElementInterface * >( domain->giveElement(ie)->giveInterface(LEPlicElementInterfaceType) ) ) ) {
416  if ( interface->giveTempVolumeFraction() > 1.0 ) {
417  OOFEM_LOG_INFO( "LEPlic::doInterfaceRemapping - Element %d: vof out of range, vof =%e", ie, interface->giveTempVolumeFraction() );
418  }
419 
420  if ( interface->giveTempVolumeFraction() >= 0.99999999 ) {
421  interface->setTempVolumeFraction(1.0);
422  }
423  }
424  }
425 
426  OOFEM_LOG_INFO("LEPlic::doInterfaceRemapping: Total volume is %e", total_volume);
427  if ( orig_reference_fluid_volume > 0.0 ) {
428  OOFEM_LOG_INFO("LEPlic::doInterfaceRemapping: Volume error is %5.2f%%\n",
429  ( ( total_volume - orig_reference_fluid_volume ) / orig_reference_fluid_volume ) * 100.0);
430  }
431 
432 
433 #ifdef __OOFEG
434  //ESIEventLoop (YES, "Step Finished; Press Ctrl-p to continue");
435  //deleteLayerGraphics(OOFEG_DEBUG_LAYER);
436 #endif
437 }
438 
439 
440 void
441 LEPlic :: doCellDLS(FloatArray &fvgrad, int ie, bool coord_upd, bool vof_temp_flag)
442 {
443  double fvi, fvk, wk, dx, dy;
444  bool isBoundaryCell = false;
445  LEPlicElementInterface *interface, *ineghbrInterface;
446  FloatMatrix lhs(2, 2);
447  FloatArray rhs(2), xi(2), xk(2);
448  IntArray currCell(1), neighborList;
449  ConnectivityTable *contable = domain->giveConnectivityTable();
450 
451  if ( ( interface = static_cast< LEPlicElementInterface * >( domain->giveElement(ie)->giveInterface(LEPlicElementInterfaceType) ) ) ) {
452  if ( vof_temp_flag ) {
453  fvi = interface->giveTempVolumeFraction();
454  } else {
455  fvi = interface->giveVolumeFraction();
456  }
457 
458  if ( ( fvi > 0. ) && ( fvi <= 1.0 ) ) {
459  // potentially boundary cell
460 
461  if ( ( fvi > 0. ) && ( fvi < 1.0 ) ) {
462  isBoundaryCell = true;
463  }
464 
465  /* DLS (Differential least square reconstruction)
466  *
467  * In the DLS method, volume fraction Taylor series expansion of vf (volume fraction)
468  * is formed from each reference cell volume fraction vf at element center x(i) to each
469  * cell neighbor at point x(k). The sum (vf(i)-vf(k))^2 over all immediate neighbors
470  * is then minimized inthe least square sense.
471  */
472  // get list of neighbours to current cell including current cell
473  currCell.at(1) = ie;
474  contable->giveElementNeighbourList(neighborList, currCell);
475  // loop over neighbors to assemble normal equations
476  interface->giveElementCenter(this, xi, coord_upd);
477  lhs.zero();
478  rhs.zero();
479  for ( int ineighbr: neighborList ) {
480  if ( ineighbr == ie ) {
481  continue; // skip itself
482  }
483 
484  if ( ( ineghbrInterface =
485  static_cast< LEPlicElementInterface * >( domain->giveElement(ineighbr)->giveInterface(LEPlicElementInterfaceType) ) ) ) {
486  if ( vof_temp_flag ) {
487  fvk = ineghbrInterface->giveTempVolumeFraction();
488  } else {
489  fvk = ineghbrInterface->giveVolumeFraction();
490  }
491 
492  if ( fvk < 1.0 ) {
493  isBoundaryCell = true;
494  }
495 
496  ineghbrInterface->giveElementCenter(this, xk, coord_upd);
497  wk = xk.distance(xi);
498  dx = ( xk.at(1) - xi.at(1) ) / wk;
499  dy = ( xk.at(2) - xi.at(2) ) / wk;
500  lhs.at(1, 1) += dx * dx;
501  lhs.at(1, 2) += dx * dy;
502  lhs.at(2, 2) += dy * dy;
503 
504  rhs.at(1) += ( fvi - fvk ) * dx / wk;
505  rhs.at(2) += ( fvi - fvk ) * dy / wk;
506  }
507  }
508 
509  if ( isBoundaryCell ) {
510  // symmetry
511  lhs.at(2, 1) = lhs.at(1, 2);
512 
513  // solve normal equation for volume fraction gradient
514  lhs.solveForRhs(rhs, fvgrad);
515 
516  // compute unit normal
517  fvgrad.normalize();
518  fvgrad.negated();
519 #ifdef __OOFEG
520  /*
521  * EASValsSetLayer(OOFEG_DEBUG_LAYER);
522  * WCRec p[2];
523  * double tx = -fvgrad.at(2), ty=fvgrad.at(1);
524  * p[0].x=xi.at(1)-tx*0.1;
525  * p[0].y=xi.at(2)-ty*0.1;
526  * p[1].x=xi.at(1)+tx*0.1;
527  * p[1].y=xi.at(2)+ty*0.1;
528  * p[0].z = p[1].z = 0.0;
529  * GraphicObj *go = CreateLine3D(p);
530  * EGWithMaskChangeAttributes(LAYER_MASK, go);
531  * EMAddGraphicsToModel(ESIModel(), go);
532  * ESIEventLoop (YES, "Cell DLS finished; Press Ctrl-p to continue");
533  */
534 #endif
535  } else {
536  fvgrad.zero();
537  }
538  }
539  }
540 }
541 
542 void
543 LEPlic :: findCellLineConstant(double &p, FloatArray &fvgrad, int ie, bool coord_upd, bool temp_vof_flag)
544 {
545  /* The line constatnt p is solved from the general non-linear function
546  * F(p) = V(p)-V = 0,
547  * where V(p) is the truncated volume resulting from the intersection between
548  * assumed line segment and the reference cell
549  * V is the given Volume of Fluid ratio
550  * To find zero of this function, Brent's method is been used.
551  */
552  Element *elem = domain->giveElement(ie);
553  LEPlicElementInterface *interface = static_cast< LEPlicElementInterface * >( elem->giveInterface(LEPlicElementInterfaceType) );
554  int nelemnodes = elem->giveNumberOfNodes();
555  double ivof, fvi;
556  double ivx, ivy, pp, target_vof;
557  if ( temp_vof_flag ) {
558  target_vof = interface->giveTempVolumeFraction();
559  } else {
560  target_vof = interface->giveVolumeFraction();
561  }
562 
563  computeLEPLICVolumeFractionWrapper wrapper(interface, this, fvgrad, target_vof, coord_upd);
564  /*
565  * Initial part: find lower and uper bounds for Brent algorithm
566  * Here lines with given interface normal are passed through each vertex
567  * and corresponding volume fractions are computed. The two lines forming
568  * truncation volumes that bound the actual material in the cell provide
569  * upper and lower bounds for line constant
570  */
571  double upper_vof = 10.0, lower_vof = -10.0;
572  double upper_p = 0.0, lower_p = 0.0;
573 
574  if ( temp_vof_flag ) {
575  fvi = interface->giveTempVolumeFraction();
576  } else {
577  fvi = interface->giveVolumeFraction();
578  }
579 
580  if ( ( fvi > LEPLIC_ZERO_VOF ) && ( fvi < 1.0 ) ) {
581  // boundary cell
582 
583 
584  for ( int ivert = 1; ivert <= nelemnodes; ivert++ ) {
585  if ( coord_upd ) {
586  ivx = giveUpdatedXCoordinate( elem->giveNode(ivert)->giveNumber() );
587  ivy = giveUpdatedYCoordinate( elem->giveNode(ivert)->giveNumber() );
588  } else {
589  ivx = elem->giveNode(ivert)->giveCoordinate(1);
590  ivy = elem->giveNode(ivert)->giveCoordinate(2);
591  }
592 
593  // determine line constant for vertex ivert
594  pp = -( fvgrad.at(1) * ivx + fvgrad.at(2) * ivy );
595  ivof = interface->computeLEPLICVolumeFraction(fvgrad, pp, this, coord_upd);
596  if ( ( ( ivof - target_vof ) >= 0. ) && ( ivof < upper_vof ) ) {
597  upper_vof = ivof;
598  upper_p = pp;
599  } else if ( ( ( target_vof - ivof ) >= 0. ) && ( ivof > lower_vof ) ) {
600  lower_vof = ivof;
601  lower_p = pp;
602  }
603  }
604 
605  if ( ( lower_vof >= 0. ) && ( upper_vof <= 1.00000000001 ) ) {
606  // now use brent's method to find minima of V(p)-V function
607  brent(lower_p, 0.5 * ( lower_p + upper_p ), upper_p,
608  mem_fun< computeLEPLICVolumeFractionWrapper >(& wrapper, & computeLEPLICVolumeFractionWrapper :: eval),
609  LEPLIC_BRENT_EPS, p);
610  //interface->setTempLineConstant (p);
611 
612 
613 #ifdef __OOFEG
614  /*
615  * Polygon grp, cell;
616  * // check here
617  * //Polygon testvolpoly;
618  * //interface->formMaterialVolumePoly(testvolpoly, this, fvgrad, p, true);
619  * //double debug_vof = interface->truncateMatVolume(testvolpoly);
620  *
621  * //printf ("Cell %d-> target_vof is %e, debug val is %e\n", ie, target_vof, debug_vof);
622  * interface->formMyVolumePoly (cell, this, true);
623  * GraphicObj *goc = cell.draw(::gc[0], false);
624  * EASValsSetLayer(OOFEG_DEBUG_LAYER);
625  * EASValsSetColor(::gc[0].getBcIcColor());
626  * EGWithMaskChangeAttributes(COLOR_MASK | LAYER_MASK, goc);
627  * EMDrawGraphics (ESIModel(), goc);
628  *
629  * interface->formVolumeInterfacePoly (grp, this, fvgrad, p, true);
630  * GraphicObj *go = grp.draw(::gc[0], true);
631  * EASValsSetColor(::gc[0].getActiveCrackColor());
632  * EGWithMaskChangeAttributes(COLOR_MASK | LAYER_MASK, go);
633  * EMDrawGraphics (ESIModel(), go);
634  * //ESIEventLoop (YES, "findCellLineConstant -> Press Ctrl-p to continue");
635  */
636 #endif
637  } else {
638  //fprintf (stderr, "target_vof = %le, fvi=%le\n", target_vof, fvi);
639  OOFEM_ERROR("finding lower and uper bounds of line constant value failed (lowerVOF = %lf, upperVOF=%lf)", lower_vof, upper_vof);
640  }
641  }
642 }
643 
646 {
647  IRResultType result;
648 
649  orig_reference_fluid_volume = 0.0;
650  IR_GIVE_OPTIONAL_FIELD(ir, orig_reference_fluid_volume, _IFT_LEPLIC_refVol);
651  return IRRT_OK;
652 }
653 
654 
655 void
657 {
658  input.setField(this->orig_reference_fluid_volume, _IFT_LEPLIC_refVol);
659 }
660 
661 
662 double
664 {
665  double dt = 1.e6;
666  LEPlicElementInterface *interface;
667 
668  for ( auto &elem : domain->giveElements() ) {
669  if ( ( interface = static_cast< LEPlicElementInterface * >( elem->giveInterface(LEPlicElementInterfaceType) ) ) ) {
670  dt = min( dt, interface->computeCriticalLEPlicTimeStep(tStep) );
671  }
672  }
673 
674  return 0.9 * dt;
675 }
676 
677 void
679 {
680  answer.resize(2);
681  Element *elem = domain->giveSpatialLocalizer()->giveElementContainingPoint(position);
682  LEPlicElementInterface *interface = static_cast< LEPlicElementInterface * >( elem->giveInterface(LEPlicElementInterfaceType) );
683  if ( interface ) {
684  Polygon pg;
685  FloatArray n;
686  interface->giveTempInterfaceNormal(n);
687  interface->formVolumeInterfacePoly(pg, this, n, interface->giveTempLineConstant(), false);
688  if ( pg.testPoint( position.at(1), position.at(2) ) ) {
689  answer.at(1) = 1.0;
690  answer.at(2) = 0.0;
691  } else {
692  answer.at(1) = 0.0;
693  answer.at(2) = 1.0;
694  }
695  } else {
696  answer.at(1) = 1.0;
697  answer.at(2) = 0.0;
698  }
699 }
700 
701 void
703 {
704  answer.resize(2);
705  Element *elem = domain->giveElement(ie);
706  LEPlicElementInterface *interface = static_cast< LEPlicElementInterface * >( elem->giveInterface(LEPlicElementInterfaceType) );
707  if ( interface ) {
708  answer.at(1) = interface->giveTempVolumeFraction();
709  answer.at(2) = 1. - answer.at(1);
710  } else {
711  answer.at(1) = 1.0;
712  answer.at(2) = 0.0;
713  }
714 }
715 
716 double
718 {
719  bool vof_1 = false, vof_0 = false;
720  double vof, vofsum = 0.0;
721  const IntArray *shelem = domain->giveConnectivityTable()->giveDofManConnectivityArray(inode);
722 
723  for ( int i = 1; i <= shelem->giveSize(); i++ ) {
724  LEPlicElementInterface *interface = static_cast< LEPlicElementInterface * >( domain->giveElement( shelem->at(i) )->giveInterface(LEPlicElementInterfaceType) );
725  if ( interface ) {
726  vof = interface->giveTempVolumeFraction();
727  if ( vof == 0.0 ) {
728  vof_0 = true;
729  } else if ( vof == 1.0 ) {
730  vof_1 = true;
731  }
732 
733  vofsum += vof;
734  }
735  }
736 
737  if ( vof_0 && vof_1 ) {
738  return 0.5;
739  } else if ( vof_0 ) {
740  return 0.0;
741  } else if ( vof_1 ) {
742  return 1.0;
743  } else {
744  return vofsum / shelem->giveSize();
745  }
746 }
747 } // end namespace oofem
void setField(int item, InputFieldType id)
contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj=NULL)
Stores context of receiver into given stream.
Definition: leplic.C:86
Element interface for LEPlic class representing Lagrangian-Eulerian (moving) material interface...
Definition: leplic.h:58
std::shared_ptr< Field > FieldPtr
Definition: field.h:72
Class and object Domain.
Definition: domain.h:115
void doInterfaceReconstruction(TimeStep *tStep, bool coord_upd, bool temp_vof)
Definition: leplic.C:241
bool solveForRhs(const FloatArray &b, FloatArray &answer, bool transpose=false)
Solves the system of linear equations .
Definition: floatmatrix.C:1112
double computeVolume() const
Definition: geotoolbox.C:72
virtual Element * giveElement()=0
Return number of receiver&#39;s element.
The purpose of DataStream abstract class is to allow to store/restore context to different streams...
Definition: datastream.h:54
contextIOResultType storeYourself(DataStream &stream) const
Definition: floatarray.C:872
void addTempVolumeFraction(double v)
Definition: leplic.h:110
double & at(int i)
Coefficient access function.
Definition: floatarray.h:131
void doCellDLS(FloatArray &fvgrad, int ie, bool coord_upd, bool temp_vof_flag)
Definition: leplic.C:441
virtual double computeCriticalLEPlicTimeStep(TimeStep *tStep)=0
Computes critical time step.
ConnectivityTable * giveConnectivityTable()
Returns receiver&#39;s associated connectivity table.
Definition: domain.C:1170
oofem::oofegGraphicContext gc[OOFEG_LAST_LAYER]
void setTempInterfaceNormal(FloatArray tg)
Definition: leplic.h:100
Abstract base class for all finite elements.
Definition: element.h:145
void giveTempInterfaceNormal(FloatArray &n)
Definition: leplic.h:120
Base class for dof managers.
Definition: dofmanager.h:113
General IO error.
virtual double giveCoordinate(int i)
Definition: node.C:82
FieldManager * giveFieldManager()
Definition: engngm.h:131
Class implementing an array of integers.
Definition: intarray.h:61
int & at(int i)
Coefficient access function.
Definition: intarray.h:103
virtual int read(int *data, int count)=0
Reads count integer values into array pointed by data.
#define THROW_CIOERR(e)
Definition: contextioerr.h:61
#define _IFT_LEPLIC_refVol
Definition: leplic.h:45
double giveTimeIncrement()
Returns solution step associated time increment.
Definition: timestep.h:150
virtual int giveNumberOfNodes() const
Returns number of nodes of receiver.
Definition: element.h:662
virtual IRResultType initializeFrom(InputRecord *ir)
Initializes receiver according to object description stored in input record.
Definition: leplic.C:645
double distance(const FloatArray &x) const
Computes the distance between position represented by receiver and position given as parameter...
Definition: floatarray.C:489
virtual int write(const int *data, int count)=0
Writes count integer values from array pointed by data.
void giveUnknownVector(FloatArray &answer, const IntArray &dofMask, ValueModeType mode, TimeStep *tStep, bool padding=false)
Assembles the vector of unknowns in global c.s for given dofs of receiver.
Definition: dofmanager.C:685
#define OOFEM_LOG_INFO(...)
Definition: logger.h:127
int giveNumber()
Returns receiver&#39;s number.
Definition: timestep.h:129
Element * giveElement(int n)
Service for accessing particular domain fe element.
Definition: domain.C:160
#define OOFEM_ERROR(...)
Definition: error.h:61
EngngModelContext * giveContext()
Context requesting service.
Definition: engngm.h:1078
double brent(double ax, double bx, double cx, const T &f, double tol, double &xmin)
Definition: mathfem.h:249
virtual void giveMaterialMixtureAt(FloatArray &answer, FloatArray &position)
Returns relative material contents at given point.
Definition: leplic.C:678
contextIOResultType restoreYourself(DataStream &stream)
Definition: floatarray.C:895
Class representing connectivity table.
virtual void giveElementCenter(LEPlic *mat_interface, FloatArray &center, bool updFlag)=0
Computes the receiver center (in updated Lagrangian configuration).
Class representing the special graph constructed from two polygons that is used to perform boolean op...
Definition: geotoolbox.h:191
TimeStep * givePreviousStep()
Returns pointer to previous solution step.
Definition: timestep.C:114
double at(int i, int j) const
Coefficient access function.
Definition: floatmatrix.h:176
void resize(int n)
Checks size of receiver towards requested bounds.
Definition: intarray.C:124
void giveElementNeighbourList(IntArray &answer, IntArray &elemList)
Returns list of neighboring elements to given elements (they are included too).
FieldPtr giveField(FieldType key)
Returns the previously registered field under given key; NULL otherwise.
Definition: fieldmanager.C:63
void findCellLineConstant(double &p, FloatArray &fvgrad, int ie, bool coord_upd, bool temp_vof_flag)
Definition: leplic.C:543
virtual void updatePosition(TimeStep *tStep)
Updates the position of interface according to state reached in given solution step.
Definition: leplic.C:135
void EVFastRedraw(EView *v_p)
EView * myview
Class representing vector of real numbers.
Definition: floatarray.h:82
#define LEPLIC_ZERO_VOF
Definition: leplic.C:49
Class representing 2D polygon.
Definition: geotoolbox.h:91
Implementation of matrix containing floating point numbers.
Definition: floatmatrix.h:94
IRResultType
Type defining the return values of InputRecord reading operations.
Definition: irresulttype.h:47
void doLagrangianPhase(TimeStep *tStep)
Definition: leplic.C:159
void setTempLineConstant(double tp)
Definition: leplic.h:99
void setTempVolumeFraction(double v)
Definition: leplic.h:101
virtual void giveElementMaterialMixture(FloatArray &answer, int ielem)
Returns volumetric (or other based measure) of relative material contents in given element...
Definition: leplic.C:702
virtual double truncateMatVolume(const Polygon &matvolpoly, double &volume)=0
Truncates given material polygon to receiver.
virtual double giveNodalScalarRepresentation(int)
Returns scalar value representation of material Interface at given point.
Definition: leplic.C:717
Class representing the general Input Record.
Definition: inputrecord.h:101
void zero()
Zeroes all coefficients of receiver.
Definition: floatarray.C:658
virtual Interface * giveInterface(InterfaceType t)
Interface requesting service.
Definition: femcmpnn.h:179
Class representing the a dynamic Input Record.
long ContextMode
Context mode (mask), defining the type of information written/read to/from context.
Definition: contextmode.h:43
contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj=NULL)
Restores context of receiver from given stream.
Definition: leplic.C:107
void deleteLayerGraphics(int iLayer)
double vof
Volume fraction of reference fluid in element.
Definition: leplic.h:63
virtual void giveInputRecord(DynamicInputRecord &input)
Setups the input record string of receiver.
Definition: leplic.C:656
virtual FloatArray * giveCoordinates()
Definition: node.h:114
void zero()
Zeroes all coefficient of receiver.
Definition: floatmatrix.C:1326
Domain * giveDomain() const
Definition: femcmpnn.h:100
int min(int i, int j)
Returns smaller value from two given decimals.
Definition: mathfem.h:59
virtual void formMaterialVolumePoly(Polygon &matvolpoly, LEPlic *matInterface, const FloatArray &normal, const double p, bool updFlag)=0
Assembles the true element material polygon (takes receiver vof into accout).
#define OOFEG_DEBUG_LAYER
int testPoint(double x, double y) const
Definition: geotoolbox.C:47
double p
Line constant of line segment representing interface.
Definition: leplic.h:65
Abstract base class representing the "problem" under consideration.
Definition: engngm.h:181
#define IR_GIVE_OPTIONAL_FIELD(__ir, __value, __id)
Macro facilitating the use of input record reading methods.
Definition: inputrecord.h:78
GraphicObj * draw(oofegGraphicContext &, bool filled, int layer=OOFEG_DEBUG_LAYER)
Definition: geotoolbox.C:152
int giveSize() const
Definition: intarray.h:203
the oofem namespace is to define a context or scope in which all oofem names are defined.
void doInterfaceRemapping(TimeStep *tStep)
Definition: leplic.C:267
Class implementing node in finite element mesh.
Definition: node.h:87
int giveNumber() const
Definition: femcmpnn.h:107
void negated()
Switches the sign of every coefficient of receiver.
Definition: floatarray.C:739
double normalize()
Normalizes receiver.
Definition: floatarray.C:828
Node * giveNode(int i) const
Returns reference to the i-th node of element.
Definition: element.h:610
#define OOFEM_WARNING(...)
Definition: error.h:62
FloatArray normal
Interface segment normal.
Definition: leplic.h:67
EngngModel * giveEngngModel()
Returns reference to itself -> required by communicator.h.
Definition: engngm.h:1117
Class representing solution step.
Definition: timestep.h:80
#define LEPLIC_BRENT_EPS
Definition: leplic.C:50
virtual double computeCriticalTimeStep(TimeStep *tStep)
Computes critical time step induced by receiver integration algorithm.
Definition: leplic.C:663
bool isBoundary()
Returns true if cell is boundary.
Definition: leplic.C:54
void resize(int s)
Resizes receiver towards requested size.
Definition: floatarray.C:631

This page is part of the OOFEM documentation. Copyright (c) 2011 Borek Patzak
Project e-mail: info@oofem.org
Generated at Tue Jan 2 2018 20:07:29 for OOFEM by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2011