OOFEM  2.4
OOFEM.org - Object Oriented Finite Element Solver
mmaleastsquareprojection.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 
36 #include "mathfem.h"
37 #include "gausspoint.h"
38 #include "element.h"
39 #include "domain.h"
40 #include "spatiallocalizer.h"
41 #include "integrationrule.h"
42 #include "connectivitytable.h"
43 #include "dynamicinputrecord.h"
44 #include "classfactory.h"
45 
46 namespace oofem {
47 REGISTER_MaterialMappingAlgorithm(MMALeastSquareProjection, MMA_LeastSquareProjection);
48 
50 {
51  this->stateFilter = 0;
52  this->regionFilter = 1;
53 }
54 
56 
57 void
58 MMALeastSquareProjection :: __init(Domain *dold, IntArray &type, const FloatArray &coords, Set &elemSet, TimeStep *tStep, bool iCohesiveZoneGP)
59 //(Domain* dold, IntArray& varTypes, GaussPoint* gp, TimeStep* tStep)
60 {
61  GaussPoint *sourceIp;
62  Element *sourceElement;
64  IntegrationRule *iRule;
65 
66  IntArray patchList;
67 
68  this->patchDomain = dold;
69  // find the closest IP on old mesh
70  sourceElement = sl->giveElementContainingPoint(coords, elemSet);
71 
72  if ( !sourceElement ) {
73  OOFEM_ERROR("no suitable source element found");
74  }
75 
76  // determine the type of patch
77  Element_Geometry_Type egt = sourceElement->giveGeometryType();
78  if ( egt == EGT_line_1 ) {
80  } else if ( ( egt == EGT_triangle_1 ) || ( egt == EGT_quad_1 ) ) {
82  } else {
83  OOFEM_ERROR("unsupported material mode");
84  }
85 
86  /* Determine the state of closest point.
87  * Only IP in the neighbourhood with same state can be used
88  * to interpolate the values.
89  */
90  FloatArray dam;
91  int state = 0;
92  if ( this->stateFilter ) {
93  iRule = sourceElement->giveDefaultIntegrationRulePtr();
94  for ( GaussPoint *gp: *iRule ) {
95  sourceElement->giveIPValue(dam, gp, IST_PrincipalDamageTensor, tStep);
96  if ( dam.computeNorm() > 1.e-3 ) {
97  state = 1; // damaged
98  }
99  }
100  }
101 
102  // from source neighbours the patch will be constructed
103  Element *element;
104  IntArray neighborList;
105  patchList.resize(1);
106  patchList.at(1) = sourceElement->giveNumber();
107  int minNumberOfPoints = this->giveNumberOfUnknownPolynomialCoefficients(this->patchType);
108  int actualNumberOfPoints = sourceElement->giveDefaultIntegrationRulePtr()->giveNumberOfIntegrationPoints();
109  int nite = 0;
110  int elemFlag;
111  // check if number of IP in patchList is sufficient
112  // some recursion control would be appropriate
113  while ( ( actualNumberOfPoints < minNumberOfPoints ) && ( nite <= 2 ) ) {
114  //if not, construct the neighborhood
115  dold->giveConnectivityTable()->giveElementNeighbourList(neighborList, patchList);
116  // count number of available points
117  patchList.clear();
118  actualNumberOfPoints = 0;
119  for ( int i = 1; i <= neighborList.giveSize(); i++ ) {
120  if ( this->stateFilter ) {
121  element = patchDomain->giveElement( neighborList.at(i) );
122  // exclude elements in different regions
123  if ( !elemSet.hasElement( element->giveNumber() ) ) {
124  continue;
125  }
126 
127  iRule = element->giveDefaultIntegrationRulePtr();
128  elemFlag = 0;
129  for ( GaussPoint *gp: *iRule ) {
130  element->giveIPValue(dam, gp, IST_PrincipalDamageTensor, tStep);
131  if ( state && ( dam.computeNorm() > 1.e-3 ) ) {
132  actualNumberOfPoints++;
133  elemFlag = 1;
134  } else if ( ( state == 0 ) && ( dam.computeNorm() < 1.e-3 ) ) {
135  actualNumberOfPoints++;
136  elemFlag = 1;
137  }
138  }
139 
140  if ( elemFlag ) {
141  // include this element with corresponding state in neighbor search.
142  patchList.followedBy(neighborList.at(i), 10);
143  }
144  } else { // if (! yhis->stateFilter)
145  element = patchDomain->giveElement( neighborList.at(i) );
146  // exclude elements in different regions
147  if ( !elemSet.hasElement( element->giveNumber() ) ) {
148  continue;
149  }
150 
151  actualNumberOfPoints += element->giveDefaultIntegrationRulePtr()->giveNumberOfIntegrationPoints();
152 
153  patchList.followedBy(neighborList.at(i), 10);
154  }
155  } // end loop over neighbor list
156 
157  nite++;
158  }
159 
160  if ( nite > 2 ) {
161  // not enough points -> take closest point projection
162  patchGPList.clear();
163  sourceIp = sl->giveClosestIP(coords, elemSet);
164  patchGPList.push_front(sourceIp);
165  //fprintf(stderr, "MMALeastSquareProjection: too many neighbor search iterations\n");
166  //exit (1);
167  return;
168  }
169 
170 #ifdef MMALSP_ONLY_CLOSEST_POINTS
171  // select only the nval closest IP points
172  GaussPoint **gpList = ( GaussPoint ** ) malloc(sizeof( GaussPoint * ) * actualNumberOfPoints);
173  FloatArray dist(actualNumberOfPoints), srcgpcoords;
174  int npoints = 0;
175  // check allocation of gpList
176  if ( gpList == NULL ) {
177  OOFEM_FATAL("memory allocation error");
178  }
179 
180  for ( int ielem = 1; ielem <= patchList.giveSize(); ielem++ ) {
181  element = patchDomain->giveElement( patchList.at(ielem) );
182  iRule = element->giveDefaultIntegrationRulePtr();
183  for ( GaussPoint *srcgp: *iRule ) {
184  if ( element->computeGlobalCoordinates( srcgpcoords, * ( srcgp->giveNaturalCoordinates() ) ) ) {
185  element->giveIPValue(dam, srcgp, IST_PrincipalDamageTensor, tStep);
186  if ( this->stateFilter ) {
187  // consider only points with same state
188  if ( ( ( state == 1 ) && ( norm(dam) > 1.e-3 ) ) || ( ( ( state == 0 ) && norm(dam) < 1.e-3 ) ) ) {
189  npoints++;
190  dist.at(npoints) = coords.distance(srcgpcoords);
191  gpList [ npoints - 1 ] = srcgp;
192  }
193  } else {
194  // take all points into account
195  npoints++;
196  dist.at(npoints) = coords.distance(srcgpcoords);
197  gpList [ npoints - 1 ] = srcgp;
198  }
199  } else {
200  OOFEM_ERROR("computeGlobalCoordinates failed");
201  }
202  }
203  }
204 
205  if ( npoints != actualNumberOfPoints ) {
206  OOFEM_ERROR("internal error");
207  }
208 
209  //minNumberOfPoints = min (actualNumberOfPoints, minNumberOfPoints+2);
210 
211  patchGPList.clear();
212  // now find the minNumberOfPoints with smallest distance
213  // from point of interest
214  double swap, minDist;
215  int minDistIndx = 0;
216  // loop over all points
217  for ( int i = 1; i <= minNumberOfPoints; i++ ) {
218  minDist = dist.at(i);
219  minDistIndx = i;
220  // search for point with i-th smallest distance
221  for ( j = i + 1; j <= actualNumberOfPoints; j++ ) {
222  if ( dist.at(j) < minDist ) {
223  minDist = dist.at(j);
224  minDistIndx = j;
225  }
226  }
227 
228  // remember this ip
229  patchGPList.push_front(gpList [ minDistIndx - 1 ]);
230  swap = dist.at(i);
231  dist.at(i) = dist.at(minDistIndx);
232  dist.at(minDistIndx) = swap;
233  srcgp = gpList [ i - 1 ];
234  gpList [ i - 1 ] = gpList [ minDistIndx - 1 ];
235  gpList [ minDistIndx - 1 ] = srcgp;
236  }
237 
238  if ( patchGPList.size() != minNumberOfPoints ) {
239  OOFEM_ERROR("internal error 2");
240  exit(1);
241  }
242 
243  free(gpList);
244 
245 #else
246 
247  // take all neighbors
248  patchGPList.clear();
249  for ( int ielem = 1; ielem <= patchList.giveSize(); ielem++ ) {
250  element = patchDomain->giveElement( patchList.at(ielem) );
251  iRule = element->giveDefaultIntegrationRulePtr();
252  for ( GaussPoint *gp: *iRule ) {
253  patchGPList.push_front( gp );
254  }
255  }
256 
257 #endif
258 }
259 
260 
261 void
263 { }
264 
265 
266 int
268  InternalStateType type, TimeStep *tStep)
269 {
270  //int nelem, ielem,
272  int nval = 0;
273  FloatArray ipVal, coords, P;
274  FloatMatrix a, rhs, x;
275  Element *element;
276  //IntegrationRule* iRule;
277 
278  a.resize(neq, neq);
279  a.zero();
280 
281  // determine the value from patch
282  int size = patchGPList.size();
283  if ( size == 1 ) {
284  GaussPoint *srcgp = *patchGPList.begin();
285  srcgp->giveElement()->giveIPValue(answer, srcgp, type, tStep);
286  } else if ( size < neq ) {
287  OOFEM_ERROR("internal error");
288  } else {
289  for ( auto &srcgp: patchGPList ) {
290  element = srcgp->giveElement();
291  element->giveIPValue(ipVal, srcgp, type, tStep);
292  if ( nval == 0 ) {
293  nval = ipVal.giveSize();
294  rhs.resize(neq, nval);
295  rhs.zero();
296  }
297  if ( element->computeGlobalCoordinates( coords, srcgp->giveNaturalCoordinates() ) ) {
298  coords.subtract(targetCoords);
299  // compute ip contribution
300  this->computePolynomialTerms(P, coords, patchType);
301  for ( int j = 1; j <= neq; j++ ) {
302  for ( int k = 1; k <= nval; k++ ) {
303  rhs.at(j, k) += P.at(j) * ipVal.at(k);
304  }
305 
306  for ( int k = 1; k <= neq; k++ ) {
307  a.at(j, k) += P.at(j) * P.at(k);
308  }
309  }
310  } else {
311  OOFEM_ERROR("computeGlobalCoordinates failed");
312  }
313  }
314 
315 #if 0
316  // check for correct solution
317  FloatMatrix aa = a;
318 #endif
319  a.solveForRhs(rhs, x);
320 #if 0
321  // check for correct solution
322  FloatMatrix tmp;
323  tmp.beProductOf(aa, x);
324  for ( j = 1; j <= neq; j++ ) {
325  for ( k = 1; k <= nval; k++ ) {
326  if ( fabs( tmp.at(j, k) - rhs.at(j, k) ) > 1.e-3 ) {
327  printf("(SE)");
328  }
329  }
330  }
331 
332 #endif
333  // determine the value from patch
334  FloatArray zeroCoords(targetCoords.giveSize()); // set to zero implicitly
335  //gp->giveElement()->computeGlobalCoordinates (coords, gp->giveNaturalCoordinates());
336  this->computePolynomialTerms(P, zeroCoords, patchType);
337 
338  answer.resize(nval);
339  answer.zero();
340  for ( int i = 1; i <= nval; i++ ) {
341  for ( int j = 1; j <= neq; j++ ) {
342  answer.at(i) += P.at(j) * x.at(j, i);
343  }
344  }
345  }
346 
347  /*
348  * double ee;
349  * aa.subtract (answer);
350  * ee = sqrt(dotProduct(aa,aa,aa.giveSize()));
351  * if ((aa.giveSize() != answer.giveSize()) || (ee > 1.e-6)) {
352  * printf("Diference @@@@@!\n");
353  * exit (1);
354  * }
355  */
356  return 1;
357 }
358 
359 int
361 {
362  OOFEM_ERROR("not implemented yet.")
363 
364  return 0;
365 }
366 
367 void
369 {
370  if ( type == MMALSPPatchType_2dq ) {
371  /*
372  * P.resize (1);
373  * P.at(1) = 1.0;
374  */
375  /*
376  * P.resize (3);
377  * P.at(1) = coords.at(1);
378  * P.at(2) = coords.at(2);
379  * P.at(3) = 1.0;
380  */
381 
382  P.resize(6);
383  P.at(1) = 1.0;
384  P.at(2) = coords.at(1);
385  P.at(3) = coords.at(2);
386  P.at(4) = coords.at(1) * coords.at(2);
387  P.at(5) = coords.at(1) * coords.at(1);
388  P.at(6) = coords.at(2) * coords.at(2);
389  } else if ( type == MMALSPPatchType_1dq ) {
390  P.resize(3);
391  P.at(1) = coords.at(1) * coords.at(1);
392  P.at(2) = coords.at(1);
393  P.at(3) = 1.0;
394  } else {
395  OOFEM_ERROR("unknown regionType");
396  }
397 }
398 
399 int
401 {
402  if ( regType == MMALSPPatchType_2dq ) {
403  return 6;
404  } else if ( regType == MMALSPPatchType_1dq ) {
405  return 3;
406  } else {
407  return 0;
408  }
409 }
410 
411 
414 {
415  IRResultType result; // Required by IR_GIVE_FIELD macro
416 
417  this->stateFilter = 0;
419 
420  this->regionFilter = 0;
422 
423  return IRRT_OK;
424 }
425 
426 
428 {
429  if ( this->stateFilter ) {
431  }
432  if ( this->regionFilter ) {
434  }
435 }
436 } // end namespace oofem
The base class for all spatial localizers.
InternalStateType
Type representing the physical meaning of element or constitutive model internal variable.
void setField(int item, InputFieldType id)
void subtract(const FloatArray &src)
Subtracts array src to receiver.
Definition: floatarray.C:258
virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep)
Returns the integration point corresponding value in full form.
Definition: element.C:1257
Class and object Domain.
Definition: domain.h:115
virtual IntegrationRule * giveDefaultIntegrationRulePtr()
Access method for default integration rule.
Definition: element.h:822
std::list< GaussPoint * > patchGPList
List of Gp participating in patch.
Element_Geometry_Type
Enumerative type used to classify element geometry Possible values are: EGT_point - point in space EG...
bool solveForRhs(const FloatArray &b, FloatArray &answer, bool transpose=false)
Solves the system of linear equations .
Definition: floatmatrix.C:1112
double & at(int i)
Coefficient access function.
Definition: floatarray.h:131
ConnectivityTable * giveConnectivityTable()
Returns receiver&#39;s associated connectivity table.
Definition: domain.C:1170
Abstract base class for all finite elements.
Definition: element.h:145
The class representing the general material model mapping algorithm.
Element * giveElement()
Returns corresponding element to receiver.
Definition: gausspoint.h:188
Class implementing an array of integers.
Definition: intarray.h:61
int & at(int i)
Coefficient access function.
Definition: intarray.h:103
int regionFilter
If set, then only IP in the same region are taken into account.
REGISTER_MaterialMappingAlgorithm(MMAClosestIPTransfer, MMA_ClosestPoint)
Abstract base class representing integration rule.
double distance(const FloatArray &x) const
Computes the distance between position represented by receiver and position given as parameter...
Definition: floatarray.C:489
virtual void __init(Domain *dold, IntArray &type, const FloatArray &coords, Set &sourceElemSet, TimeStep *tStep, bool iCohesiveZoneGP=false)
Initializes the receiver state before mapping.
Element * giveElement(int n)
Service for accessing particular domain fe element.
Definition: domain.C:160
#define OOFEM_FATAL(...)
Macros for printing errors.
Definition: error.h:60
#define OOFEM_ERROR(...)
Definition: error.h:61
void clear()
Clears the array (zero size).
Definition: intarray.h:177
Set of elements, boundaries, edges and/or nodes.
Definition: set.h:66
SpatialLocalizer * giveSpatialLocalizer()
Returns receiver&#39;s associated spatial localizer.
Definition: domain.C:1184
#define _IFT_MMALeastSquareProjection_statefilter
virtual ~MMALeastSquareProjection()
Destructor.
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
virtual Element * giveElementContainingPoint(const FloatArray &coords, const IntArray *regionList=NULL)=0
Returns the element, containing given point and belonging to one of the region in region list...
void giveElementNeighbourList(IntArray &answer, IntArray &elemList)
Returns list of neighboring elements to given elements (they are included too).
virtual void finish(TimeStep *tStep)
Finishes the mapping for given time step.
int stateFilter
If set, then only IP in the neighbourhood with same state can be used to interpolate the values...
Abstract base class representing a material status information.
Definition: matstatus.h:84
void computePolynomialTerms(FloatArray &P, const FloatArray &coords, MMALeastSquareProjectionPatchType type)
Class representing vector of real numbers.
Definition: floatarray.h:82
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
virtual IRResultType initializeFrom(InputRecord *ir)
double norm(const FloatArray &x)
Definition: floatarray.C:985
double computeNorm() const
Computes the norm (or length) of the vector.
Definition: floatarray.C:840
void resize(int rows, int cols)
Checks size of receiver towards requested bounds.
Definition: floatmatrix.C:1358
Class representing the general Input Record.
Definition: inputrecord.h:101
virtual void giveInputRecord(DynamicInputRecord &input)
Setups the input record of receiver.
void followedBy(const IntArray &b, int allocChunk=0)
Appends array b at the end of receiver.
Definition: intarray.C:145
int giveNumberOfIntegrationPoints() const
Returns number of integration points of receiver.
void zero()
Zeroes all coefficients of receiver.
Definition: floatarray.C:658
Class representing the a dynamic Input Record.
int giveNumberOfUnknownPolynomialCoefficients(MMALeastSquareProjectionPatchType regType)
#define _IFT_MMALeastSquareProjection_regionfilter
void zero()
Zeroes all coefficient of receiver.
Definition: floatmatrix.C:1326
MMALeastSquareProjectionPatchType patchType
Type of patch.
#define IR_GIVE_OPTIONAL_FIELD(__ir, __value, __id)
Macro facilitating the use of input record reading methods.
Definition: inputrecord.h:78
void beProductOf(const FloatMatrix &a, const FloatMatrix &b)
Assigns to the receiver product of .
Definition: floatmatrix.C:337
int giveSize() const
Definition: intarray.h:203
int giveSize() const
Returns the size of receiver.
Definition: floatarray.h:218
virtual Element_Geometry_Type giveGeometryType() const
Returns the element geometry type.
Definition: element.C:1529
the oofem namespace is to define a context or scope in which all oofem names are defined.
virtual GaussPoint * giveClosestIP(const FloatArray &coords, int region, bool iCohesiveZoneGP=false)=0
Returns the integration point in associated domain, which is closest to given point.
int giveNumber() const
Definition: femcmpnn.h:107
virtual int mapStatus(MaterialStatus &oStatus) const
Initializes receiver according to object description stored in input record.
Class representing integration point in finite element program.
Definition: gausspoint.h:93
bool hasElement(int elem) const
Return True if given element is contained.
Definition: set.C:218
Class representing solution step.
Definition: timestep.h:80
virtual int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords)
Computes the global coordinates from given element&#39;s local coordinates.
Definition: element.C:1207
virtual int __mapVariable(FloatArray &answer, const FloatArray &coords, InternalStateType type, TimeStep *tStep)
Maps and update the unknown of given type from old mesh oldd to new mesh to which gp belongs to...
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:30 for OOFEM by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2011