OOFEM  2.4
OOFEM.org - Object Oriented Finite Element Solver
nonlocalmaterialext.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 "gausspoint.h"
36 #include "floatarray.h"
37 #include "element.h"
38 #include "timestep.h"
39 #include "integrationrule.h"
40 #include "nonlocalmaterialext.h"
41 #include "material.h"
42 #include "spatiallocalizer.h"
43 #include "domain.h"
44 #include "nonlocalbarrier.h"
45 #include "mathfem.h"
46 #include "dynamicinputrecord.h"
47 
48 #ifdef __PARALLEL_MODE
49  #include "parallel.h"
50 #endif
51 
52 #include <list>
53 
54 namespace oofem {
55 // flag forcing the inclusion of all elements with volume inside support of weight function.
56 // This forces inclusion of all integration points of these elements, even if weight is zero
57 // If not defined (default) only integration points with nonzero weight are included.
58 // #define NMEI_USE_ALL_ELEMENTS_IN_SUPPORT
59 
60 
61 // constructor
63 {
64  domain = d;
65  regionMap.resize( d->giveNumberOfRegions() ); /*lastUpdatedStateCounter = 0;*/
66  if ( this->hasBoundedSupport() ) {
68  } else {
70  }
71 
72  cl = 0.;
73  suprad = 0.;
74  mm = 0.;
78 
79  cl0 = 0.;
80  beta = 0.;
81  zeta = 0.;
83 
84  px = 0.;
85 
86  Rf = 0.;
87  exponent = 1.;
88  averType = 0;
89 
90  gridSize = 0;
91  grid = NULL;
92  minDist2 = NULL;
93  initDiag = 0.;
94  order = 1;
95  centDiff = 2;
96 }
97 
98 void
100 {
101  Domain *d = this->giveDomain();
102 
104  return; // already updated
105  }
106 
107  OOFEM_LOG_DEBUG("Updating Before NonlocAverage\n");
108  for ( auto &elem : d->giveElements() ) {
109  elem->updateBeforeNonlocalAverage(tStep);
110  }
111 
112  // mark last update counter to prevent multiple updates
114 }
115 
116 void
118 {
119  double elemVolume, integrationVolume = 0.;
120 
124  if ( !statusExt ) {
125  OOFEM_ERROR("local material status encountered");
126  }
127 
128  if ( !statusExt->giveIntegrationDomainList()->empty() ) {
129  return; // already done
130  }
131 
132  // Compute the volume around the Gauss point and store it in the nonlocal material status
133  // (it will be used by modifyNonlocalWeightFunctionAround)
134  elemVolume = gp->giveElement()->computeVolumeAround(gp);
135  statusExt->setVolumeAround(elemVolume);
136 
137  auto iList = statusExt->giveIntegrationDomainList();
138 
139  FloatArray gpCoords, jGpCoords, shiftedGpCoords;
140  if ( gp->giveElement()->computeGlobalCoordinates( gpCoords, gp->giveNaturalCoordinates() ) == 0 ) {
141  OOFEM_ERROR("computeGlobalCoordinates of target failed");
142  }
143 
144  // If nonlocal variation is set to the distance-based approach, a new nonlocal radius
145  // is calculated as a function of the distance from the Gauss point to the nonlocal boundaries
147  // cl=cl0;
150  }
151 
152  // If the mesh represents a periodic cell, nonlocal interaction is considered not only for the real neighbors
153  // but also for their periodic images, shifted by +px or -px in the x-direction. In the implementation,
154  // instead of shifting the potential neighbors, we shift the receiver point gp. In the non-periodic case (typical),
155  // px=0 and the following loop is executed only once.
156 
157  int nx = 0; // typical case
158  if ( px > 0. ) {
159  nx = 1; // periodicity taken into account
160  }
161  for ( int ix = -nx; ix <= nx; ix++ ) { // loop over periodic images shifted in x-direction
163  shiftedGpCoords = gpCoords;
164  shiftedGpCoords.at(1) += ix * px;
165 
166  // ask domain spatial localizer for list of elements with IP within this zone
167 #ifdef NMEI_USE_ALL_ELEMENTS_IN_SUPPORT
168  this->giveDomain()->giveSpatialLocalizer()->giveAllElementsWithNodesWithinBox(elemSet, shiftedGpCoords, suprad);
169  // insert element containing given gp
170  elemSet.insert( gp->giveElement()->giveNumber() );
171 #else
173 #endif
174  // initialize iList
175  iList->reserve(elemSet.giveSize());
176  for ( auto elindx : elemSet ) {
177  Element *ielem = this->giveDomain()->giveElement(elindx);
178  if ( regionMap.at( ielem->giveRegionNumber() ) == 0 ) {
179  for ( auto &jGp : *ielem->giveDefaultIntegrationRulePtr() ) {
180  if ( ielem->computeGlobalCoordinates( jGpCoords, jGp->giveNaturalCoordinates() ) ) {
181  double weight = this->computeWeightFunction(shiftedGpCoords, jGpCoords);
182 
183  //manipulate weights for a special averaging of strain (OFF by default)
184  this->manipulateWeight(weight, gp, jGp);
185 
186  this->applyBarrierConstraints(shiftedGpCoords, jGpCoords, weight);
187 #ifdef NMEI_USE_ALL_ELEMENTS_IN_SUPPORT
188  if ( 1 ) {
189 #else
190  if ( weight > 0. ) {
191 #endif
193  ir.nearGp = jGp; // store gp
194  elemVolume = weight * jGp->giveElement()->computeVolumeAround(jGp);
195  ir.weight = elemVolume; // store gp weight
196  iList->push_back(ir); // store own copy in list
197  integrationVolume += elemVolume;
198  }
199  } else {
200  OOFEM_ERROR("computeGlobalCoordinates of target failed");
201  }
202  }
203  }
204  } // loop over elements
205  iList->shrink_to_fit();
206  }
207 
208  statusExt->setIntegrationScale(integrationVolume); // store scaling factor
209 }
210 
211 void
213 {
214  double weight, elemVolume, integrationVolume = 0.;
215 
219 
220  if ( !statusExt ) {
221  OOFEM_ERROR("local material status encountered");
222  }
223 
224  auto iList = statusExt->giveIntegrationDomainList();
225  iList->clear();
226 
227  if ( contributingElems == NULL ) {
228  // no element table provided, use standard method
229  this->buildNonlocalPointTable(gp);
230  } else {
231  FloatArray gpCoords, jGpCoords;
232  int _size = contributingElems->giveSize();
233  if ( gp->giveElement()->computeGlobalCoordinates( gpCoords, gp->giveNaturalCoordinates() ) == 0 ) {
234  OOFEM_ERROR("computeGlobalCoordinates of target failed");
235  }
236 
237  //If nonlocal variation is set to the distance-based approach calculates new nonlocal radius
238  // based on the distance from the nonlocal boundaries
240  cl = cl0;
243  }
244 
245  // initialize iList
246  iList->reserve(_size);
247  for ( int _e = 1; _e <= _size; _e++ ) {
248  Element *ielem = this->giveDomain()->giveElement( contributingElems->at(_e) );
249  if ( regionMap.at( ielem->giveRegionNumber() ) == 0 ) {
250  for ( auto &jGp : *ielem->giveDefaultIntegrationRulePtr() ) {
251  if ( ielem->computeGlobalCoordinates( jGpCoords, jGp->giveNaturalCoordinates() ) ) {
252  weight = this->computeWeightFunction(gpCoords, jGpCoords);
253 
254  //manipulate weights for a special averaging of strain (OFF by default)
255  this->manipulateWeight(weight, gp, jGp);
256 
257  this->applyBarrierConstraints(gpCoords, jGpCoords, weight);
258 #ifdef NMEI_USE_ALL_ELEMENTS_IN_SUPPORT
259  if ( 1 ) {
260 #else
261  if ( weight > 0. ) {
262 #endif
264  ir.nearGp = jGp; // store gp
265  elemVolume = weight * jGp->giveElement()->computeVolumeAround(jGp);
266  ir.weight = elemVolume; // store gp weight
267  iList->push_back(ir); // store own copy in list
268  integrationVolume += elemVolume;
269  }
270  } else {
271  OOFEM_ERROR("computeGlobalCoordinates of target failed");
272  }
273  }
274  }
275  } // loop over elements
276 
277  statusExt->setIntegrationScale(integrationVolume); // remember scaling factor
278 #ifdef __PARALLEL_MODE
279  #ifdef __VERBOSE_PARALLEL
280  fprintf( stderr, "%d(%d):", gp->giveElement()->giveGlobalNumber(), gp->giveNumber() );
281  for ( auto &lir : *iList ) {
282  fprintf(stderr, "%d,%d(%e)", lir.nearGp->giveElement()->giveGlobalNumber(), lir.nearGp->giveNumber(), lir.weight);
283  }
284 
285  fprintf(stderr, "\n");
286  #endif
287 #endif
288  }
289 }
290 
291 // This is the method used by eikonal nonlocal models to adjust the nonlocal interaction
292 // depending on the evolution of some internal variables such as damage
293 void
295 {
296  Element *elem = gp->giveElement();
297  FloatArray coords;
298  elem->computeGlobalCoordinates( coords, gp->giveNaturalCoordinates() );
299  int dim = coords.giveSize();
300  if ( dim == 1 ) {
302  return;
303  }
304 
305 #ifdef DEBUG
306  if ( dim != 2 ) {
307  OOFEM_ERROR("NonlocalMaterialExtensionInterface :: modifyNonlocalWeightFunctionAround is implemented only for 1D and 2D problems, sorry.\n");
308  }
309 #endif
310 
311  // Compute the "speed" at each grid node, depending on damage or a similar variable (note that "speed" will be deleted by grid)
313  // This is a simple initialization that leads to standard Euclidean distance
314  /*
315  * for (i=1; i<=2*gridSize+1; i++)
316  * for (j=1; j<=2*gridSize+1; j++)pos
317  * speed->at(i,j) = 1.;
318  */
319 
320  auto *list = this->giveIPIntegrationList(gp);
321  Element *ngpElem;
322  FloatArray ngpCoords(2);
323 
324  // This is the proper initialization for a truly eikonal damage model
325 
326  // Loop over neighboring Gauss points - transfer of damage to the grid "speed"
327  double xgp = coords.at(1);
328  double ygp = coords.at(2);
329  int ipos = 0;
330  double xngp, yngp, damgp;
331  for ( auto lip : *list ) {
332  ipos++;
333  // Determine the global coordinates of the neighboring Gauss point
334  ngpElem = ( lip.nearGp )->giveElement();
335  ngpElem->computeGlobalCoordinates( ngpCoords, lip.nearGp->giveNaturalCoordinates() );
336  // Get damage at the neighboring Gauss point
337  xngp = mapToGridCoord(ngpCoords.at(1), xgp);
338  yngp = mapToGridCoord(ngpCoords.at(2), ygp);
339  damgp = this->giveNonlocalMetricModifierAt(lip.nearGp);
340  // For the first neighbor, set damage as initial guess
341  if ( ipos == 1 ) {
342  for ( int i = 1; i <= 2 * gridSize + 1; i++ ) {
343  for ( int j = 1; j <= 2 * gridSize + 1; j++ ) {
344  minDist2->at(i, j) = dist2FromGridNode(xngp, yngp, j, i);
345  speed->at(i, j) = damgp;
346  }
347  }
348  // For the other neighbors, check whether distance is smaller and update damage
349  } else {
350  for ( int i = 1; i <= 2 * gridSize + 1; i++ ) {
351  for ( int j = 1; j <= 2 * gridSize + 1; j++ ) {
352  double dist2 = dist2FromGridNode(xngp, yngp, j, i);
353  if ( dist2 < minDist2->at(i, j) ) {
354  minDist2->at(i, j) = dist2;
355  speed->at(i, j) = damgp;
356  }
357  }
358  }
359  }
360  }
361 
362  // Transform damage to speed
363  for ( int i = 1; i <= 2 * gridSize + 1; i++ ) {
364  for ( int j = 1; j <= 2 * gridSize + 1; j++ ) {
365  speed->at(i, j) = 1. / computeDistanceModifier( speed->at(i, j) );
366  }
367  }
368 
369  // Initialize grid for distance evaluation
370  grid->unFreeze();
371 
372  // Set the details of the method that should be used by the grid
374 
375  // Set zero distance at the grid center
376  FloatMatrix center(1, 2);
377  center.at(1, 1) = center.at(1, 2) = ( double ) gridSize + 1;
378  grid->setZeroValues(& center);
379 
380  // The fast marching method will be invoked implicitly, by asking for the solution
381 
382  double wsum = 0.;
383  // Loop over neighboring Gauss points - evaluation of new weights
384  for ( auto lip : *list ) {
385  // Determine the global coordinates of a neighboring Gauss point
386  ngpElem = ( lip.nearGp )->giveElement();
387  ngpElem->computeGlobalCoordinates( ngpCoords, lip.nearGp->giveNaturalCoordinates() );
388  // Find the nearest node of the grid (transformation from physical coordinates to grid coordinates)
389  int j = mapToGridPoint( ngpCoords.at(1), coords.at(1) );
390  if ( j < 1 ) {
391  j = 1;
392  } else if ( j > 2 * gridSize + 1 ) {
393  j = 2 * gridSize + 1;
394  }
395  int i = mapToGridPoint( ngpCoords.at(2), coords.at(2) );
396  if ( i < 1 ) {
397  i = 1;
398  } else if ( i > 2 * gridSize + 1 ) {
399  i = 2 * gridSize + 1;
400  }
401 
402  // Get solution value from the nearest grid point
403  double distance = ( suprad / gridSize ) * grid->giveSolutionValueAt(i, j);
404  if ( distance < 0. ) {
405  printf("Warning\n");
406  }
407  // Compute and store the weight function for that distance
408  // double volumeAround = ngpElem->computeVolumeAround(lip.nearGp); // old style
409  // More efficient:
411  static_cast< NonlocalMaterialStatusExtensionInterface * >( lip.nearGp->giveMaterialStatus()->
413  double volumeAround = statusExt->giveVolumeAround();
414  double w = computeWeightFunction(distance) * volumeAround;
415  lip.weight = w;
416  wsum += w;
417  }
418 
419  // update the stored sum of nonlocal interaction weights (to be used for potential rescaling)
423  statusExt->setIntegrationScale(wsum);
424 }
425 
426 // Simple algorithm, limited to 1D, can be used for comparison
427 void
429 {
430  auto *list = this->giveIPIntegrationList(gp);
431  std :: vector< localIntegrationRecord > :: iterator postarget;
432 
433  // find the current Gauss point (target) in the list of it neighbors
434  for ( auto pos = list->begin(); pos != list->end(); ++pos ) {
435  if ( pos->nearGp == gp ) {
436  postarget = pos;
437  }
438  }
439 
440  Element *elem = gp->giveElement();
441  FloatArray coords;
442  elem->computeGlobalCoordinates( coords, gp->giveNaturalCoordinates() );
443  double xtarget = coords.at(1);
444 
445  double w, wsum = 0., x, xprev, damage, damageprev = 0.;
446  Element *nearElem;
447 
448  // process the list from the target to the end
449  double distance = 0.; // distance modified by damage
450  xprev = xtarget;
451  for ( auto pos = postarget; pos != list->end(); ++pos ) {
452  nearElem = ( pos->nearGp )->giveElement();
453  nearElem->computeGlobalCoordinates( coords, pos->nearGp->giveNaturalCoordinates() );
454  x = coords.at(1);
455  damage = this->giveNonlocalMetricModifierAt(pos->nearGp);
456  /*
457  * nonlocStatus = static_cast< IDNLMaterialStatus * >( this->giveStatus(pos->nearGp) );
458  * damage = nonlocStatus->giveTempDamage();
459  * if ( damage == 0. ) {
460  * damage = nonlocStatus->giveDamage();
461  * }
462  */
463 
464  if ( pos != postarget ) {
465  distance += computeModifiedLength(x - xprev, damage, damageprev);
466  //( x - xprev ) * 0.5 * ( computeDistanceModifier(damage) + computeDistanceModifier(damageprev) );
467  }
468 
469  w = computeWeightFunction(distance) * nearElem->computeVolumeAround(pos->nearGp);
470  pos->weight = w;
471  wsum += w;
472  xprev = x;
473  damageprev = damage;
474  }
475 
476  // process the list from the target to the beginning
477  distance = 0.;
478  for ( auto pos = postarget; pos != list->begin(); --pos ) {
479  nearElem = ( pos->nearGp )->giveElement();
480  nearElem->computeGlobalCoordinates( coords, pos->nearGp->giveNaturalCoordinates() );
481  x = coords.at(1);
482  damage = this->giveNonlocalMetricModifierAt(pos->nearGp);
483  /*
484  * nonlocStatus = static_cast< IDNLMaterialStatus * >( this->giveStatus(pos->nearGp) );
485  * damage = nonlocStatus->giveTempDamage();
486  * if ( damage == 0. ) {
487  * damage = nonlocStatus->giveDamage();
488  * }
489  */
490 
491  if ( pos != postarget ) {
492  distance += computeModifiedLength(xprev - x, damage, damageprev);
493  //distance += ( xprev - x ) * 0.5 * ( computeDistanceModifier(damage) + computeDistanceModifier(damageprev) );
494  w = computeWeightFunction(distance) * nearElem->computeVolumeAround(pos->nearGp);
495  pos->weight = w;
496  wsum += w;
497  }
498 
499  xprev = x;
500  damageprev = damage;
501  }
502 
503  // the beginning must be treated separately
504  auto pos = list->begin();
505  if ( pos != postarget ) {
506  nearElem = ( pos->nearGp )->giveElement();
507  nearElem->computeGlobalCoordinates( coords, pos->nearGp->giveNaturalCoordinates() );
508  x = coords.at(1);
509  damage = this->giveNonlocalMetricModifierAt(pos->nearGp);
510  /*
511  * nonlocStatus = static_cast< IDNLMaterialStatus * >( this->giveStatus(pos->nearGp) );
512  * damage = nonlocStatus->giveTempDamage();
513  * if ( damage == 0. ) {
514  * damage = nonlocStatus->giveDamage();
515  * }
516  */
517 
518  distance += computeModifiedLength(xprev - x, damage, damageprev);
519  //distance += ( xprev - x ) * 0.5 * ( computeDistanceModifier(damage) + computeDistanceModifier(damageprev) );
520  w = computeWeightFunction(distance) * nearElem->computeVolumeAround(pos->nearGp);
521  pos->weight = w;
522  wsum += w;
523  }
524 
525  // update the stored sum of nonlocal interaction weights (to be used for potential rescaling)
529  statusExt->setIntegrationScale(wsum);
530 }
531 
532 double
533 NonlocalMaterialExtensionInterface :: computeModifiedLength(double length, double dam1, double dam2)
534 {
535  if ( averType == 6 ) { // different (improved) integration scheme
536  return length * 2. / ( 1. / computeDistanceModifier(dam1) + 1. / computeDistanceModifier(dam2) );
537  } else { // standard integration scheme
538  //printf("%g %g %g %g %g %g\n",dam1,dam2,computeDistanceModifier(dam1),computeDistanceModifier(dam2),length,length * 0.5 * ( computeDistanceModifier(dam1) + computeDistanceModifier(dam2) ));
539  return length * 0.5 * ( computeDistanceModifier(dam1) + computeDistanceModifier(dam2) );
540  }
541 }
542 
543 double
545 {
546  switch ( averType ) {
547  case 2: return 1. / ( Rf / cl + ( 1. - Rf / cl ) * pow(1. - damage, exponent) );
548 
549  case 3: if ( damage == 0. ) {
550  return 1.;
551  } else {
552  return 1. / ( 1. - ( 1. - Rf / cl ) * pow(damage, exponent) );
553  }
554 
555  case 4: return 1. / pow(Rf / cl, damage);
556 
557  case 5: return ( 2. * cl ) / ( cl + Rf + ( cl - Rf ) * cos(M_PI * damage) );
558 
559  case 6: return 1. / sqrt(1. - damage);
560 
561  default: return 1.;
562  }
563 }
564 
565 std :: vector< localIntegrationRecord > *
567 {
571 
572  if ( !statusExt ) {
573  OOFEM_ERROR("local material status encountered");
574  }
575 
576  if ( statusExt->giveIntegrationDomainList()->empty() ) {
577  this->buildNonlocalPointTable(gp);
578  }
579 
580  return statusExt->giveIntegrationDomainList();
581 }
582 
583 void
585 {
589 
590  if ( !statusExt ) {
591  OOFEM_ERROR("local material status encountered");
592  }
593 
594  if ( ( !this->hasBoundedSupport() ) || ( !permanentNonlocTableFlag ) ) {
595  statusExt->clear();
596  }
597 }
598 
599 double
601 {
602  if ( weightFun == WFT_UniformOverElement ) { // uniform function over one element
603  return 1.;
604  }
605 
606  if ( distance > suprad || distance < 0. ) {
607  return 0.;
608  }
609 
610  double aux = distance / this->cl;
612 
613  switch ( weightFun ) {
614  case WFT_Bell: // Bell shaped function (quartic spline)
615  aux = ( 1. - aux * aux );
616  return aux * aux / iwf;
617 
618  case WFT_Gauss: // Gauss function
619  return exp(-aux * aux) / iwf;
620 
621  case WFT_Green: // Function corresponding in 1D to Green's function of Helmholtz equation (implicit gradient model)
622  //printf("%14g %14g\n",distance,exp(-aux) / iwf);
623  return exp(-aux) / iwf;
624 
625  case WFT_Green_21: // Green function reduced from 2D to 1D
626  {
627  /*
628  * if (this->domain->giveNumberOfSpatialDimensions() != 1){
629  * OOFEM_ERROR("this type of weight function can be used for a 1D problem only");
630  * }
631  */
632  iwf = giveIntegralOfWeightFunction(2); // indeed
633  double x = distance;
634  double y = 0.;
635  double r = sqrt(x * x + y * y);
636  double sum = exp(-r / this->cl);
637  double h = this->cl / 10.; // 10 could later be replaced by an optional parameter
638  do {
639  y += h;
640  r = sqrt(x * x + y * y);
641  sum += 2. * exp(-r / this->cl);
642  } while ( r <= suprad );
643  //printf("%14g %14g\n",distance,sum * h / iwf);
644  return sum * h / iwf;
645  }
646 
647  case WFT_Uniform: // uniform function over an interaction distance
648  return 1. / iwf;
649 
650  default:
651  OOFEM_WARNING("unknown type of weight function %d", weightFun);
652  return 0.0;
653  }
654 }
655 
656 double
658 {
659  return computeWeightFunction( src.distance(coord) );
660 }
661 
662 double
664 {
665  const double pi = M_PI;
666  switch ( weightFun ) {
667  case WFT_Bell:
668  switch ( spatial_dimension ) {
669  case 1: return cl * 16. / 15.;
670 
671  case 2: return cl * cl * pi / 3.;
672 
673  case 3: return cl * cl * cl * pi * 32. / 105.;
674 
675  default: return 1.;
676  }
677 
678  case WFT_Gauss:
679  switch ( spatial_dimension ) {
680  case 1: return cl * sqrt(pi);
681 
682  case 2: return cl * cl * pi;
683 
684  case 3: return cl * cl * cl * sqrt(pi * pi * pi);
685 
686  default: return 1.;
687  }
688 
689  case WFT_Green:
690  case WFT_Green_21:
691  switch ( spatial_dimension ) {
692  case 1: return cl * 2.;
693 
694  case 2: return cl * cl * 2. * pi;
695 
696  case 3: return cl * cl * cl * 8. * pi;
697 
698  default: return 1.;
699  }
700 
701  case WFT_Uniform:
702  switch ( spatial_dimension ) {
703  case 1: return cl * 2.;
704 
705  case 2: return cl * cl * pi;
706 
707  case 3: return cl * cl * cl * ( 4. / 3. ) * pi;
708 
709  default: return 1.;
710  }
711 
712  default: return 1.;
713  }
714 }
715 
716 double
718 {
720  return 1. / iwf;
721 }
722 
723 double
725 {
726  switch ( weightFun ) {
727  case WFT_Bell: return cl;
728 
729  case WFT_Gauss: return 2.5 * cl;
730 
731  case WFT_Green: case WFT_Green_21: return 6. * cl;
732 
733  case WFT_Uniform: return cl;
734 
735  case WFT_UniformOverElement: return 0.0; // to make sure that only Gauss points of the same element will be considered as neighbors
736 
737  default: return cl;
738  }
739 }
740 
741 
744 {
745  IRResultType result; // Required by IR_GIVE_FIELD macro
746 
749  if ( regionMap.giveSize() != this->giveDomain()->giveNumberOfRegions() ) {
750  OOFEM_ERROR("regionMap size mismatch");
751  }
752  } else {
753  regionMap.zero();
754  }
755 
756  if ( this->hasBoundedSupport() ) {
758  } else {
759  permanentNonlocTableFlag = false;
760  }
762 
763  // read the characteristic length
765  if ( cl < 0.0 ) {
766  cl = 0.0;
767  }
768 
769  // read the type of weight function
770  int val = WFT_Bell;
772  this->weightFun = ( WeightFunctionType ) val;
773 
774  // this is introduced for compatibility of input format with previous versions
775  // ("averagingtype 1" in the input means that the weight function
776  // should be uniform over an element,
777  // which can now be described as "wft 5")
778  int avt = 0;
780  if ( avt == 1 ) {
782  }
783 
784  // evaluate the support radius based on type of weight function and characteristic length
786 
787  // read the optional parameter for overnonlocal formulation
788  mm = 1.;
790 
791  // read the type of scaling
792  val = ST_Standard;
794  this->scaling = ( ScalingType ) val;
795 
796  // read the type of averaged variable
797  val = AVT_EqStrain;
799  this->averagedVar = ( AveragedVarType ) val;
800 
801  // read the nonlocal variation type (default is zero)
802  cl0 = cl;
803  int nlvariation = 0;
805  if ( nlvariation == 1 ) {
809  } else if ( nlvariation == 2 ) {
812  } else if ( nlvariation == 3 ) {
816  }
817 
818  // read the periodic shift (default is zero)
819  px = 0.;
821 
822  // read parameters used by models with variable characteristic length (eikonal nonlocal models)
823  averType = 0;
825  if ( averType == 2 ) {
826  exponent = 0.5; // default value for averaging type 2
827  }
828 
829  if ( averType == 3 ) {
830  exponent = 1.; // default value for averaging type 3
831  }
832 
833  if ( averType == 2 || averType == 3 ) {
835  }
836 
837  if ( averType >= 2 && averType <= 5 ) {
839  }
840 
841  if ( averType >= 2 && averType <= 6 ) { // eikonal models
842  gridSize = 10; // default value
844  grid = new Grid(2 *gridSize + 1, 2 *gridSize + 1);
845  minDist2 = new FloatMatrix(2 *gridSize + 1, 2 *gridSize + 1);
846  order = 1; // default value
848  initDiag = 0.; // default value
850  centDiff = 2; // default value
852  }
853 
854  return IRRT_OK;
855 }
856 
857 
859 {
860  if ( regionMap.giveSize() ) {
862  }
870 
874  } else if ( nlvar == NLVT_StressBased ) {
876  }
877 
879  if ( averType == 2 || averType == 3 ) {
881  }
882  if ( averType >= 2 && averType <= 5 ) {
884  }
885 }
886 
887 
888 
889 //int NonlocalMaterialExtension :: giveElementRegion (Element* element) {return element->giveCrossSection()->giveNumber();}
890 //int NonlocalMaterialExtension :: giveNumberOfRegions () {return domain->giveNumberOfCrossSectionModels();}
891 
892 /*
893  * bool
894  * NonlocalMaterialExtensionInterface::isBarrierActivated (const FloatArray& c1, const FloatArray& c2) const
895  * {
896  * int ib, nbarrier = domain->giveNumberOfNonlocalBarriers();
897  *
898  * for (ib=1; ib<=nbarrier; ib++) {
899  * if (domain->giveNonlocalBarrier(ib)->isActivated(c1,c2))
900  * return true;
901  * }
902  *
903  * return false;
904  * }
905  */
906 
907 void
909 {
910  int ib, nbarrier = domain->giveNumberOfNonlocalBarriers();
911  bool shieldFlag = false;
912 
913  for ( ib = 1; ib <= nbarrier; ib++ ) {
914  domain->giveNonlocalBarrier(ib)->applyConstraint(gpCoords, jGpCoords, weight, shieldFlag, this);
915  if ( shieldFlag ) {
916  weight = 0.0;
917  return;
918  }
919  }
920 }
921 
922 void
924 {
925  Element *ielem = jGp->giveElement();
927 
928  if ( ielem->giveMaterial()->hasProperty(AVERAGING_TYPE, jGp) ) {
929  if ( ielem->giveMaterial()->give(AVERAGING_TYPE, jGp) == 1 ) {
930  weight = 1. / ( iRule->giveNumberOfIntegrationPoints() ); //assign the same weights over the whole element
931  }
932  }
933 }
934 
935 
936 double
938 {
939  double distance = 1.e10; // Initially distance from the boundary is set to the maximum value
940  double temp;
941  int ib, nbarrier = domain->giveNumberOfNonlocalBarriers();
942  for ( ib = 1; ib <= nbarrier; ib++ ) { //Loop over all the nonlocal barriers to find minimum distance from the boundary
944  if ( distance > temp ) { //Check to find minimum distance from boundary from all nonlocal boundaries
945  distance = temp;
946  }
947  }
948 
949  //Calculate interaction radius based on the minimum distance from the nonlocal boundaries
950  double newradius = 0.0;
951  if ( nlvar == NLVT_DistanceBasedLinear ) {
952  if ( distance < zeta * cl0 ) {
953  newradius = ( 1. - beta ) / ( zeta * cl0 ) * distance + beta;
954  } else {
955  newradius = 1.;
956  }
957  } else if ( nlvar == NLVT_DistanceBasedExponential ) {
958  newradius = 1. - ( 1. - beta ) * exp( -distance / ( zeta * cl0 ) );
959  }
960  return newradius * cl0;
961 }
963 
965 {
966  integrationScale = 0.;
967  volumeAround = 0.;
968 }
969 
971 {
972  ;
973 }
974 } // end namespace oofem
WeightFunctionType
Type characterizing the nonlocal weight function.
#define _IFT_NonlocalMaterialExtensionInterface_r
void setField(int item, InputFieldType id)
#define _IFT_NonlocalMaterialExtensionInterface_exp
int giveRegionNumber()
Definition: element.C:507
double beta
Parameter which multiplied with the interaction radius cl0 gives its minimum allowed value...
void updateDomainBeforeNonlocAverage(TimeStep *tStep)
Updates data in all integration points before nonlocal average takes place.
void modifyNonlocalWeightFunctionAround(GaussPoint *gp)
Recompute the nonlocal interaction weights based on the current solution (e.g., on the damage field)...
Class and object Domain.
Definition: domain.h:115
double exponent
Parameter used as an exponent by models with evolving characteristic length.
void endIPNonlocalAverage(GaussPoint *gp)
Notifies the receiver, that the nonlocal averaging has been finished for given ip.
virtual IntegrationRule * giveDefaultIntegrationRulePtr()
Access method for default integration rule.
Definition: element.h:822
ScalingType
Type characterizing the scaling approach.
void setMethod(int o, double i, int c)
Set the details of the algorithm to be used.
Definition: grid.h:49
virtual double evaluateSupportRadius()
Determines the width (radius) of limited support of weighting function.
#define _IFT_NonlocalMaterialExtensionInterface_regionmap
double giveSolutionValueAt(int i, int j)
Output methods.
Definition: grid.C:204
virtual void giveAllElementsWithIpWithinBox_EvenIfEmpty(elementContainerType &elemSet, const FloatArray &coords, const double radius)=0
Returns container (set) of all domain elements having integration point within given box...
#define _IFT_NonlocalMaterialExtensionInterface_nonlocalvariation
virtual void applyConstraint(const FloatArray &c1, const FloatArray &c2, double &weight, bool &shieldFlag, NonlocalMaterialExtensionInterface *nei)=0
Abstract method modifying the integration weight between master (c1) and source (c2) point...
void unFreeze()
Set all flags to "unfrozen".
Definition: grid.C:95
virtual double calculateMinimumDistanceFromBoundary(const FloatArray &coords)=0
Abstract method calculating the minimum distance of the Gauss Point from the nonlocal boundaries...
#define _IFT_NonlocalMaterialExtensionInterface_gridsize
AveragedVarType averagedVar
Parameter specifying the type of averaged (nonlocal) variable.
NonlocalBarrier * giveNonlocalBarrier(int n)
Service for accessing particular domain nonlocal barrier representation.
Definition: domain.C:351
void zero()
Sets all component to zero.
Definition: intarray.C:52
double & at(int i)
Coefficient access function.
Definition: floatarray.h:131
int giveGlobalNumber() const
Definition: element.h:1059
Domain * giveDomain()
Returns reference to domain.
void applyBarrierConstraints(const FloatArray &gpCoords, const FloatArray &jGpCoords, double &weight)
void setNonlocalUpdateStateCounter(StateCounterType val)
sets the value of nonlocalUpdateStateCounter
Definition: domain.h:693
virtual void giveAllElementsWithNodesWithinBox(elementContainerType &elemSet, const FloatArray &coords, const double radius)
Returns container (set) of all domain elements having node within given box.
virtual double giveNonlocalMetricModifierAt(GaussPoint *gp)
Provide the current value of the variable that affects nonlocal interaction (e.g., of damage) This method is used e.g.
NlVariationType nlvar
Parameter specifying the type of nonlocal variation.
virtual bool hasField(InputFieldType id)=0
Returns true if record contains field identified by idString keyword.
void buildNonlocalPointTable(GaussPoint *gp)
Builds list of integration points which take part in nonlocal average in given integration point...
Abstract base class for all finite elements.
Definition: element.h:145
bool permanentNonlocTableFlag
Flag indicating whether to keep nonlocal interaction tables of integration points cached...
Element * giveElement()
Returns corresponding element to receiver.
Definition: gausspoint.h:188
Abstract base class for all nonlocal constitutive model statuses.
ScalingType scaling
Parameter specifying the type of scaling of nonlocal weight function.
std::vector< localIntegrationRecord > * giveIntegrationDomainList()
Returns integration list of receiver.
int giveNumberOfSpatialDimensions()
Returns number of spatial dimensions.
Definition: domain.C:1067
#define OOFEM_LOG_DEBUG(...)
Definition: logger.h:128
Class implementing an array of integers.
Definition: intarray.h:61
int & at(int i)
Coefficient access function.
Definition: intarray.h:103
#define _IFT_NonlocalMaterialExtensionInterface_wft
double weight
Corresponding integration weight.
AveragedVarType
Type characterizing the averaged (nonlocal) variable.
virtual int hasBoundedSupport()
Determines, whether receiver has bounded weighting function (limited support).
FloatMatrix * givePrescribedField()
Definition: grid.h:54
#define _IFT_NonlocalMaterialExtensionInterface_averagingtype
Abstract base class representing integration rule.
WeightFunctionType weightFun
Parameter specifying the type of nonlocal weight function.
#define _IFT_NonlocalMaterialExtensionInterface_permanentNonlocTableFlag
double zeta
Parameter used when Distance-based nonlocal variation is applied When it is multiplied with the inter...
double computeDistanceModifier(double damage)
Compute the factor that specifies how the interaction length should be modified, based on the current...
IRResultType initializeFrom(InputRecord *ir)
int averType
Parameter specifying how the weight function should be adjusted due to damage.
double distance(const FloatArray &x) const
Computes the distance between position represented by receiver and position given as parameter...
Definition: floatarray.C:489
FloatMatrix * minDist2
Auxiliary matrix to store minimum distances of grid points from Gauss points.
virtual double give(int aProperty, GaussPoint *gp)
Returns the value of material property &#39;aProperty&#39;.
Definition: material.C:52
#define _IFT_NonlocalMaterialExtensionInterface_initdiag
int gridSize
Grid on which the eikonal equation will be solved (used by eikonal nonlocal models) ...
virtual double computeVolumeAround(GaussPoint *gp)
Returns volume related to given integration point.
Definition: element.h:518
double giveDistanceBasedInteractionRadius(const FloatArray &gpCoords)
Provides the distance based interaction radius This function is called when nlvariation is set to 1...
#define _IFT_NonlocalMaterialExtensionInterface_rf
NonlocalMaterialExtensionInterface(Domain *d)
Constructor.
Element * giveElement(int n)
Service for accessing particular domain fe element.
Definition: domain.C:160
StateCounterType giveNonlocalUpdateStateCounter()
Returns the value of nonlocalUpdateStateCounter.
Definition: domain.h:691
#define M_PI
Definition: mathfem.h:52
double cl0
Initial(user defined) characteristic length of the nonlocal model (its interpretation depends on the ...
double px
Parameter specifying the periodic shift in x-direction.
StateCounterType giveSolutionStateCounter()
Returns current solution state counter.
Definition: timestep.h:188
#define _IFT_NonlocalMaterialExtensionInterface_centdiff
void modifyNonlocalWeightFunction_1D_Around(GaussPoint *gp)
#define OOFEM_ERROR(...)
Definition: error.h:61
#define _IFT_NonlocalMaterialExtensionInterface_px
GaussPoint * nearGp
Reference to influencing integration point.
void clear()
clears the integration list of receiver
int giveNumber()
Returns number of receiver.
Definition: gausspoint.h:184
void setZeroValues(FloatMatrix *gridCoords)
Methods setting the values of the unknown field at selected points (e.g., zero times) ...
Definition: grid.C:105
#define _IFT_NonlocalMaterialExtensionInterface_m
std::vector< localIntegrationRecord > * giveIPIntegrationList(GaussPoint *gp)
Returns integration list corresponding to given integration point.
Class that solves certain problems on a regular 2D grid, consisting of n x m nodes.
Definition: grid.h:32
SpatialLocalizer * giveSpatialLocalizer()
Returns receiver&#39;s associated spatial localizer.
Definition: domain.C:1184
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
#define _IFT_NonlocalMaterialExtensionInterface_scalingtype
#define _IFT_NonlocalMaterialExtensionInterface_beta
double dist2FromGridNode(double x, double y, int j, int i)
Class representing vector of real numbers.
Definition: floatarray.h:82
#define AVERAGING_TYPE
Definition: matconst.h:95
double giveIntegralOfWeightFunction(const int spatial_dimension)
Provides the integral of the weight function over the contributing volume in 1, 2 or 3D...
void rebuildNonlocalPointTable(GaussPoint *gp, IntArray *contributingElems)
Rebuild list of integration points which take part in nonlocal average in given integration point...
#define _IFT_NonlocalMaterialExtensionInterface_zeta
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 setIntegrationScale(double val)
Sets associated integration scale.
void manipulateWeight(double &weight, GaussPoint *gp, GaussPoint *jGp)
Manipulates weight on integration point in the element.
double mm
For "undernonlocal" or "overnonlocal" formulation.
IntegrationPointStatus * giveMaterialStatus()
Returns reference to associated material status (NULL if not defined).
Definition: gausspoint.h:205
Class representing the general Input Record.
Definition: inputrecord.h:101
double initDiag
Optional parameters setting details of the fast marching method.
IntArray regionMap
Map indicating regions to skip (region - cross section model).
Class Interface.
Definition: interface.h:82
int giveNumberOfIntegrationPoints() const
Returns number of integration points of receiver.
int giveNumberOfNonlocalBarriers() const
Returns number of nonlocal integration barriers.
Definition: domain.h:448
virtual double maxValueOfWeightFunction()
Determines the maximum value of the nonlocal weight function.
Class representing the a dynamic Input Record.
int giveNumberOfRegions() const
Returns number of regions. Currently regions corresponds to cross section models. ...
Definition: domain.h:446
#define _IFT_NonlocalMaterialExtensionInterface_order
#define _IFT_NonlocalMaterialExtensionInterface_averagedquantity
double integrationScale
Nonlocal volume around the corresponding integration point.
double volumeAround
Local volume around the corresponding integration point.
std::vector< std::unique_ptr< Element > > & giveElements()
Definition: domain.h:279
#define IR_GIVE_OPTIONAL_FIELD(__ir, __value, __id)
Macro facilitating the use of input record reading methods.
Definition: inputrecord.h:78
int giveSize() const
Definition: intarray.h:203
int giveSize() const
Returns the size of receiver.
Definition: floatarray.h:218
the oofem namespace is to define a context or scope in which all oofem names are defined.
virtual bool hasProperty(int aProperty, GaussPoint *gp)
Returns true if &#39;aProperty&#39; exists on material.
Definition: material.C:70
#define IR_GIVE_FIELD(__ir, __value, __id)
Macro facilitating the use of input record reading methods.
Definition: inputrecord.h:69
int giveNumber() const
Definition: femcmpnn.h:107
void setVolumeAround(double val)
Sets associated integration scale.
double cl
Characteristic length of the nonlocal model (its interpretation depends on the type of weight functio...
Class representing integration point in finite element program.
Definition: gausspoint.h:93
#define OOFEM_WARNING(...)
Definition: error.h:62
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
double Rf
Final value of interaction radius, for a model with evolving characteristic length.
double giveVolumeAround()
Returns associated volume.
virtual double computeWeightFunction(double distance)
Evaluates the basic nonlocal weight function for a given distance between interacting points...
const FloatArray & giveNaturalCoordinates()
Returns coordinate array of receiver.
Definition: gausspoint.h:138
Structure containing reference to integration point and its corresponding nonlocal integration weight...
virtual Material * giveMaterial()
Definition: element.C:484
double computeModifiedLength(double length, double dam1, double dam2)
Compute the modified interaction length based on the current solution (e.g., on the damage field)...
void giveInputRecord(DynamicInputRecord &input)
Stores receiver in an input record.

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