OOFEM  2.4
OOFEM.org - Object Oriented Finite Element Solver
fastmarchingmethod.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 "fastmarchingmethod.h"
36 #include "domain.h"
37 #include "mathfem.h"
38 #include "node.h"
39 #include "element.h"
40 #include "connectivitytable.h"
41 
42 #include <cstdlib>
43 
44 namespace oofem {
45 void
47  const std :: list< int > &bcDofMans,
48  double F)
49 {
50  int candidate;
52 
53 
54  this->dmanValuesPtr = & dmanValues;
55  // tag points with boundary value as known
56  // then tag as trial all points that are one grid point away
57  // finally tag as far all other grid points
58  this->initialize(dmanValues, bcDofMans, F);
59 
60  // let candidate be the thrial point with smallest T value
61  while ( ( candidate = this->getSmallestTrialDofMan() ) ) {
62  // add the candidate to known, remove it from trial
63  dmanRecords.at(candidate - 1).status = FMM_Status_KNOWN;
64  // tag as trial all neighbors of candidate that are not known
65  // if the neighbor is in far, remove and add it to the trial set
66  // and recompute the values of T at all trial neighbors of candidate
67  for ( int neighborElem: *ct->giveDofManConnectivityArray(candidate) ) {
68  Element *ie = domain->giveElement( neighborElem );
69  for ( int jn: ie->giveDofManArray() ) {
70  if ( dmanRecords.at(jn - 1).status != FMM_Status_KNOWN ) {
71  // recompute the value of T at candidate trial neighbor
72  this->updateTrialValue(dmanValues, jn, F);
73  }
74  }
75  }
76  }
77 }
78 
79 
80 
81 void
83  const std :: list< int > &bcDofMans,
84  double F)
85 {
86  // tag points with boundary value as known
87  // then tag as trial all points that are one grid point away
88  // finally tag as far all other grid points
89  int i;
90  int nnode = domain->giveNumberOfDofManagers();
92 
93  // all points are far by default
94  dmanRecords.resize(nnode);
95  for ( i = 0; i < nnode; i++ ) {
96  dmanRecords [ i ].status = FMM_Status_FAR;
97  }
98 
99  // first tag all boundary points
100 
101  for ( int jnode: bcDofMans ) {
102  if ( jnode > 0 ) {
103  dmanRecords.at(jnode - 1).status = FMM_Status_KNOWN;
104  } else {
105  dmanRecords.at(-jnode - 1).status = FMM_Status_KNOWN_BOUNDARY;
106  }
107  }
108 
109  // tag as trial all points that are one grid point away
110  for ( int jnode: bcDofMans ) {
111  jnode = abs(jnode);
112 
113  for ( int neighbor: *ct->giveDofManConnectivityArray(jnode) ) {
115  if ( neighbor == i ) {
116  continue;
117  }
118 
119  Element *neighborElem = domain->giveElement( neighbor );
120  for ( int neighborNode: neighborElem->giveDofManArray() ) {
121  if ( ( dmanRecords.at(neighborNode - 1).status != FMM_Status_KNOWN ) &&
122  ( dmanRecords.at(neighborNode - 1).status != FMM_Status_KNOWN_BOUNDARY ) &&
123  ( dmanRecords.at(neighborNode - 1).status != FMM_Status_TRIAL ) ) {
124  this->updateTrialValue(dmanValues, neighborNode, F);
125  }
126  }
127  }
128  }
129 }
130 
131 
132 void
134 {
135  int ai, bi, ci, h, nroot, _ind = 0;
136  double at, bt, ht, a, b, u, cos_fi, sin_fi, _a, _b, _c, r1, r2, r3, t = 0.0, _h;
137  bool reg_upd_flag;
138  FloatArray *ac, *bc, *cc, cb, ca;
140 
141 
142  // first look for suitable element that can produce admissible value
143  // algorithm limited to non-obtuse 2d triangulations
144  for ( int neighborElem: *ct->giveDofManConnectivityArray(id) ) {
145  // test element if admissible
146  Element *ie = domain->giveElement( neighborElem );
147  if ( ie->giveGeometryType() == EGT_triangle_1 ) {
148  for ( int j = 1; j <= 3; j++ ) {
149  if ( ie->giveDofManagerNumber(j) == id ) {
150  _ind = j;
151  }
152  }
153 
154  ci = ie->giveDofManagerNumber(_ind);
155  ai = ie->giveDofManagerNumber(1 + ( _ind ) % 3);
156  bi = ie->giveDofManagerNumber(1 + ( _ind + 1 ) % 3);
157 
158  if ( ( dmanRecords.at(ai - 1).status == FMM_Status_KNOWN ) &&
159  ( dmanRecords.at(bi - 1).status == FMM_Status_KNOWN ) ) {
160  at = dmanValues.at(ai);
161  bt = dmanValues.at(bi);
162  if ( fabs(at) > fabs(bt) ) {
163  h = ai;
164  ai = bi;
165  bi = h;
166  ht = at;
167  at = bt;
168  bt = ht;
169  }
170 
171  // get nodal coordinates
172  ac = domain->giveNode(ai)->giveCoordinates();
173  bc = domain->giveNode(bi)->giveCoordinates();
174  cc = domain->giveNode(ci)->giveCoordinates();
175 
176  // a = distance of BC
177  a = cc->distance(bc);
178  // b = distance of AC
179  b = cc->distance(ac);
180  // compute fi angle
181  cb.beDifferenceOf(* bc, * cc);
182  cb.normalize();
183  ca.beDifferenceOf(* ac, * cc);
184  ca.normalize();
185  cos_fi = cb.dotProduct(ca);
186  sin_fi = sqrt(1.0 - cos_fi * cos_fi);
187  u = fabs(bt);
188  // compute quadratic equation coefficients for t
189  _a = ( a * a + b * b - 2.0 * a * b * cos_fi );
190  _b = 2.0 * b * u * ( a * cos_fi - b );
191  _c = b * b * ( u * u - F * F * a * a * sin_fi * sin_fi );
192  cubic3r(0.0, _a, _b, _c, & r1, & r2, & r3, & nroot);
193  reg_upd_flag = true;
194 
195  if ( nroot == 0 ) {
196  reg_upd_flag = false;
197  } else if ( nroot == 1 ) {
198  t = r1;
199  } else if ( r1 >= 0.0 ) {
200  t = r1;
201  } else if ( r2 >= 0.0 ) {
202  t = r2;
203  } else {
204  reg_upd_flag = false;
205  }
206 
207  if ( reg_upd_flag ) {
208  _h = b * ( t - u ) / t;
209  if ( ( t > u ) && ( _h > a * cos_fi ) && ( _h < a / cos_fi ) ) {
210  if ( dmanRecords.at(ci - 1).status == FMM_Status_FAR ) {
211  dmanValues.at(ci) = sgn(F) * t + at;
212  } else if ( F > 0. ) {
213  dmanValues.at(ci) = min(dmanValues.at(ci), sgn(F) * t + at);
214  } else {
215  dmanValues.at(ci) = max(dmanValues.at(ci), sgn(F) * t + at);
216  }
217  } else {
218  reg_upd_flag = false;
219  }
220  }
221 
222  if ( !reg_upd_flag ) {
223  if ( F > 0. ) {
224  _h = min(b * F + at, a * F + bt);
225  } else {
226  _h = max(b * F + at, a * F + bt);
227  }
228 
229  if ( dmanRecords.at(ci - 1).status == FMM_Status_FAR ) {
230  dmanValues.at(ci) = _h;
231  } else if ( F > 0. ) {
232  dmanValues.at(ci) = min(dmanValues.at(ci), _h);
233  } else {
234  dmanValues.at(ci) = max(dmanValues.at(ci), _h);
235  }
236  }
237 
238  // if not yet in queue (trial for the first time), put it there
239  if ( dmanRecords.at(ci - 1).status != FMM_Status_TRIAL ) {
240  dmanTrialQueue.push(ci);
241  }
242 
243  dmanRecords.at(ci - 1).status = FMM_Status_TRIAL;
244  } // admissible triangle
245  } // end EGT_triangle_1 element type
246  }
247 }
248 
249 int
251 {
252  int answer;
253  if ( dmanTrialQueue.empty() ) {
254  return 0;
255  }
256 
257  answer = dmanTrialQueue.top();
258  dmanTrialQueue.pop();
259  return answer;
260 }
261 } // end namespace oofem
void updateTrialValue(FloatArray &dmanValues, int id, double F)
Updates the distance of trial node with given id).
int giveDofManagerNumber(int i) const
Translates local to global indices for dof managers.
Definition: element.h:590
int giveNumberOfDofManagers() const
Returns number of dof managers in domain.
Definition: domain.h:432
double & at(int i)
Coefficient access function.
Definition: floatarray.h:131
int max(int i, int j)
Returns bigger value form two given decimals.
Definition: mathfem.h:71
double sgn(double i)
Returns the signum of given value (if value is < 0 returns -1, otherwise returns 1) ...
Definition: mathfem.h:91
ConnectivityTable * giveConnectivityTable()
Returns receiver&#39;s associated connectivity table.
Definition: domain.C:1170
Abstract base class for all finite elements.
Definition: element.h:145
Boundary nodes, from which the front will not propagate.
std::vector< FMM_DofmanRecord > dmanRecords
Array of DofManager records.
void beDifferenceOf(const FloatArray &a, const FloatArray &b)
Sets receiver to be a - b.
Definition: floatarray.C:341
const FloatArray * dmanValuesPtr
Pointer to working set of dmanValues.
void solve(FloatArray &dmanValues, const std::list< int > &bcDofMans, double F)
Solution of problem.
double distance(const FloatArray &x) const
Computes the distance between position represented by receiver and position given as parameter...
Definition: floatarray.C:489
const IntArray & giveDofManArray() const
Definition: element.h:592
Element * giveElement(int n)
Service for accessing particular domain fe element.
Definition: domain.C:160
void cubic3r(double a, double b, double c, double d, double *r1, double *r2, double *r3, int *num)
Solves cubic equation for real roots, assuming that if cubic polynomial given then the only possibili...
Definition: mathfem.C:155
double dotProduct(const FloatArray &x) const
Computes the dot product (or inner product) of receiver and argument.
Definition: floatarray.C:463
Trial nodes, candidates for known (accepted).
std::priority_queue< int, std::vector< int >, FMM_DofmanRecordDelegate_greater > dmanTrialQueue
Priority queue for trial T values.
Class representing connectivity table.
void initialize(FloatArray &dmanValues, const std::list< int > &bcDofMans, double F)
Initialize receiver.
Class representing vector of real numbers.
Definition: floatarray.h:82
const IntArray * giveDofManConnectivityArray(int dofman)
int getSmallestTrialDofMan()
Get the trial point with smallest T; zero if empty.
virtual FloatArray * giveCoordinates()
Definition: node.h:114
int min(int i, int j)
Returns smaller value from two given decimals.
Definition: mathfem.h:59
virtual Element_Geometry_Type giveGeometryType() const
Returns the element geometry type.
Definition: element.C:1529
Node * giveNode(int n)
Service for accessing particular domain node.
Definition: domain.h:371
the oofem namespace is to define a context or scope in which all oofem names are defined.
double normalize()
Normalizes receiver.
Definition: floatarray.C:828

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:28 for OOFEM by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2011