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

This page is part of the OOFEM-3.0 documentation. Copyright Copyright (C) 1994-2025 Borek Patzak Bořek Patzák
Project e-mail: oofem@fsv.cvut.cz
Generated at for OOFEM by doxygen 1.15.0 written by Dimitri van Heesch, © 1997-2011