OOFEM 3.0
Loading...
Searching...
No Matches
solutionbasedshapefunction.C
Go to the documentation of this file.
1/*
2 * solutionbasedshapefunction.C
3 *
4 * Created on: May 27, 2013
5 * Author: carl
6 */
7
10#include "activebc.h"
11#include "activedof.h"
12#include "inputrecord.h"
13#include "element.h"
14#include "node.h"
15#include "masterdof.h"
16#include "sparsemtrx.h"
17#include "gausspoint.h"
19#include "mathfem.h"
20#include "fei2dtrlin.h"
21#include "fei2dtrquad.h"
22#include "classfactory.h"
23#include "set.h"
24#include "util.h"
25#include "inputrecord.h"
26#include "engngm.h"
27#include "spatiallocalizer.h"
28#include "dynamicinputrecord.h"
29#include "bodyload.h"
30#include "boundarycondition.h"
31//#include "stokesflow.h"
32//#include "classfactory.h"
33
34#include <vector>
35
36namespace oofem {
37template< class T >
38void logData(T myArray) {
39 for ( int xyz = 1; xyz <= myArray.giveSize(); xyz++ ) {
40 if ( dynamic_cast< IntArray * >(& myArray) ) {
41 printf( "%u ", myArray.at(xyz) );
42 } else {
43 printf( "%f ", myArray.at(xyz) );
44 }
45 }
46}
47
48template< class T >
49void logDataMsg(const char *c, T myArray) {
50 printf("%s ", c);
51 logData(myArray);
52 printf("\n");
53}
54
55template< class T >
56void logDataMsg(const char *c, T myArray, const char *c2) {
57 printf("%s ", c);
58 logData(myArray);
59 printf("%s\n", c2);
60}
61
63
64SolutionbasedShapeFunction :: SolutionbasedShapeFunction(int n, Domain *d) : ActiveBoundaryCondition(n, d),
65 order(8),
66 TOL(1e-5),
67 isLoaded(false),
68 bigNorm(0.0)
69{}
70
71
72void
73SolutionbasedShapeFunction :: initializeFrom(InputRecord &ir)
74{
75 ActiveBoundaryCondition :: initializeFrom(ir);
76
77 // Load problem file
78 this->filename = "";
80 useConstantBase = ( this->filename == "" ) ? true : false;
81
82 externalSet = -1;
84
85 // use correction factors to ensure incompressibility
88
89 dumpSnapshot = false;
91
92
93 // Set up master dofs
95 myNode = new Node( 1, this->giveDomain() );
96
97 for (int i = 1; i <= this->giveDomain()->giveNumberOfSpatialDimensions(); i++) {
98 int DofID = this->domain->giveNextFreeDofID();
99 MasterDof *newDof = new MasterDof( myNode, (DofIDItem) DofID );
100 myNode->appendDof( newDof );
101 }
102
103 init();
104}
105
107SolutionbasedShapeFunction :: giveInternalDofManager(int i)
108{
109 return myNode;
110}
111
112bool
113SolutionbasedShapeFunction :: isCoeff(ActiveDof *dof)
114{
115 for ( Dof *myDof: *myNode ) {
116 if ( dof == myDof ) {
117 return true;
118 }
119 }
120 return false;
121}
122
123void
124SolutionbasedShapeFunction :: init()
125{
126 Node *n1 = this->giveDomain()->giveNode(1);
127
130
131 for ( auto &n :this->giveDomain()->giveDofManagers() ) {
132 for ( int j = 1; j <= maxCoord.giveSize(); j++ ) {
133 maxCoord.at(j) = max( n->giveCoordinate(j), maxCoord.at(j) );
134 minCoord.at(j) = min( n->giveCoordinate(j), minCoord.at(j) );
135 }
136 }
137}
138
139void
140SolutionbasedShapeFunction :: computeCorrectionFactors(modeStruct &myMode, IntArray &Dofs, double &am, double &ap)
141{
142 /*
143 * *Compute c0, cp, cm, Bp, Bm, Ap and Am
144 */
145
146 double A0p = 0.0, App = 0.0, A0m = 0.0, Amm = 0.0, Bp = 0.0, Bm = 0.0, c0 = 0.0, cp = 0.0, cm = 0.0;
147
148 EngngModel &model = *myMode.myEngngModel;
149 Set *mySet = model.giveDomain(1)->giveSet(externalSet);
150
151 IntArray BoundaryList = mySet->giveBoundaryList();
152
153 for ( int i = 0; i < BoundaryList.giveSize() / 2; i++ ) {
154 int ElementID = BoundaryList[2 * i];
155 int Boundary = BoundaryList[2 * i + 1];
156
157 Element *thisElement = model.giveDomain(1)->giveElement(ElementID);
158 FEInterpolation *geoInterpolation = thisElement->giveInterpolation();
159 IntArray zNodes, pNodes, mNodes;
160 FloatMatrix nodeValues;
161
162 auto bnodes = geoInterpolation->boundaryGiveNodes(Boundary, thisElement->giveGeometryType() );
163
164 nodeValues.resize( this->dofs.giveSize(), bnodes.giveSize() );
165 nodeValues.zero();
166
167 // Change to global ID for bnodes and identify the intersection of bnodes and the zero boundary
168 splitBoundaryNodeIDs(myMode, * thisElement, bnodes, pNodes, mNodes, zNodes, nodeValues);
169
170 std :: unique_ptr< IntegrationRule >iRule(geoInterpolation->giveBoundaryIntegrationRule(order, Boundary, thisElement->giveGeometryType()));
171
172 for ( auto &gp: *iRule ) {
173 const FloatArray &lcoords = gp->giveNaturalCoordinates();
174 FloatArray gcoords, normal, N;
175 FloatArray Phi;
176
177 double detJ = fabs( geoInterpolation->boundaryGiveTransformationJacobian( Boundary, lcoords, FEIElementGeometryWrapper(thisElement) ) ) * gp->giveWeight();
178
179 geoInterpolation->boundaryEvalNormal( normal, Boundary, lcoords, FEIElementGeometryWrapper(thisElement) );
180 geoInterpolation->boundaryEvalN( N, Boundary, lcoords, FEIElementGeometryWrapper(thisElement) );
181 geoInterpolation->boundaryLocal2Global( gcoords, Boundary, lcoords, FEIElementGeometryWrapper(thisElement) );
182
183 FloatArray pPhi(Dofs.giveSize()), mPhi(Dofs.giveSize()), zPhi(Dofs.giveSize());
184
185 // Build phi (analytical averaging, not projected onto the mesh)
186 computeBaseFunctionValueAt(Phi, gcoords, Dofs, *myMode.myEngngModel);
187
188 // Build zPhi for this DofID
189 for ( int l = 1; l <= zNodes.giveSize(); l++ ) {
190 int nodeID = zNodes.at(l);
191 for ( int m = 1; m <= this->dofs.giveSize(); m++ ) {
192 zPhi.at(m) += N.at(nodeID) * nodeValues.at(m, nodeID);
193 }
194 }
195
196
197 // Build pPhi for this DofID
198 for ( int l = 1; l <= pNodes.giveSize(); l++ ) {
199 int nodeID = pNodes.at(l);
200 for ( int m = 1; m <= this->dofs.giveSize(); m++ ) {
201 pPhi.at(m) += N.at(nodeID) * nodeValues.at(m, nodeID);
202 }
203 }
204
205 // Build mPhi for this DofID
206 for ( int l = 1; l <= mNodes.giveSize(); l++ ) {
207 int nodeID = mNodes.at(l);
208 for ( int m = 1; m <= this->dofs.giveSize(); m++ ) {
209 mPhi.at(m) += N.at(nodeID) * nodeValues.at(m, nodeID);
210 }
211 }
212
213 c0 += zPhi.dotProduct(normal, 3) * detJ;
214 cp += pPhi.dotProduct(normal, 3) * detJ;
215 cm += mPhi.dotProduct(normal, 3) * detJ;
216
217 App += pPhi.dotProduct(pPhi, 3) * detJ;
218 Amm += mPhi.dotProduct(mPhi, 3) * detJ;
219 A0p += zPhi.dotProduct(pPhi, 3) * detJ;
220 A0m += zPhi.dotProduct(mPhi, 3) * detJ;
221
222 Bp += Phi.dotProduct(pPhi, 3) * detJ;
223 Bm += Phi.dotProduct(mPhi, 3) * detJ;
224 }
225 }
226
227 am = -( A0m * cp * cp - Bm * cp * cp - A0p * cm * cp + App * c0 * cm + Bp * cm * cp ) / ( App * cm * cm + Amm * cp * cp );
228 ap = -( A0p * cm * cm - Bp * cm * cm - A0m * cm * cp + Amm * c0 * cp + Bm * cm * cp ) / ( App * cm * cm + Amm * cp * cp );
229}
230
231void
232SolutionbasedShapeFunction :: splitBoundaryNodeIDs(modeStruct &mode, Element &e, IntArray &bnodes, IntArray &pList, IntArray &mList, IntArray &zList, FloatMatrix &nodeValues)
233{
234 pList.clear();
235 mList.clear();
236 zList.clear();
237
238 for ( int j = 1; j <= bnodes.giveSize(); j++ ) {
239 DofManager *dman = e.giveDofManager( bnodes.at(j) );
240
241 bool isZero = false;
242 bool isPlus = false;
243 bool isMinus = false;
244
245 whichBoundary(dman->giveCoordinates(), isPlus, isMinus, isZero);
246
247 if ( isZero ) {
248 zList.insertSorted(j);
249 } else if ( isPlus ) {
250 pList.insertSorted(j);
251 } else if ( isMinus ) {
252 mList.insertSorted(j);
253 }
254
255 // Find global DofManager and fetch nodal values
256 for ( size_t k = 0; k < mode.SurfaceData.size(); k++ ) {
257 if ( mode.SurfaceData[k].DofMan == dman ) {
258 int IndexOfDofIDItem = 0;
259 for ( int l = 1; l <= dofs.giveSize(); l++ ) {
260 if ( dofs.at(l) == mode.SurfaceData[k].DofID ) {
261 IndexOfDofIDItem = l;
262 break;
263 }
264 }
265 nodeValues.at(IndexOfDofIDItem, j) = mode.SurfaceData[k].value;
266 }
267 }
268 }
269}
270
271double
272SolutionbasedShapeFunction :: giveUnknown(PrimaryField &field, ValueModeType mode, TimeStep *tStep, ActiveDof *dof)
273{
274 return this->giveUnknown(mode, tStep, dof);
275}
276
277double
278SolutionbasedShapeFunction :: giveUnknown(ValueModeType mode, TimeStep *tStep, ActiveDof *dof)
279{
280 // Return value of pertinent quantity in coordinate given by dof
281
282 FloatArray shapeFunctionValues;
283 computeDofTransformation(dof, shapeFunctionValues);
284
285 FloatArray gamma;
286 myNode->giveUnknownVector(gamma, myDofIDs, mode, tStep); // alpha1, alpha2,...
287
288 double out = shapeFunctionValues.dotProduct(gamma);
289
290 return out;
291}
292
293void
294SolutionbasedShapeFunction :: computeDofTransformation(ActiveDof *dof, FloatArray &masterContribs)
295{
296 if ( !isLoaded ) {
297 loadProblem();
298 }
299
300 FloatArray values, masterContribs2, d, values2;
301
302 masterContribs.resize( this->giveDomain()->giveNumberOfSpatialDimensions() );
303 masterContribs2.resize( this->giveDomain()->giveNumberOfSpatialDimensions() );
304
305 IntArray dofIDs = {dof->giveDofID()};
306
307 bool isPlus, isMinus, isZero, found;
308 whichBoundary(dof->giveDofManager()->giveCoordinates(), isPlus, isMinus, isZero);
309
310 for ( int i = 0; i < this->giveDomain()->giveNumberOfSpatialDimensions(); i++ ) {
311 double factor = 1.0;
312 found = false;
313
314 modeStruct &ms = modes[i];
315 for ( size_t j = 0; j < ms.SurfaceData.size(); j++ ) {
316 SurfaceDataStruct &sd = ms.SurfaceData[j];
317 if ( sd.DofMan->giveNumber() == dof->giveDofManager()->giveNumber() ) {
318 if ( sd.DofID == dof->giveDofID() ) {
319 values.resize(1);
320 values.at(1) = sd.value;
321 found = true;
322 break;
323 }
324 }
325 }
326
327 if ( !found ) {
328 printf( "%u\n", dof->giveDofManager()->giveNumber() );
329 OOFEM_ERROR("Node not found");
330 }
331
332 //giveValueAtPoint(values2, *dof->giveDofManager()->giveCoordinates(), dofIDs, *modes.at(i-1)->myEngngModel);
333 //printf ("Mode %u, DofManager: %u, DofIDItem %u, value %10.10f\n", i, dof->giveDofManager()->giveNumber(), dof->giveDofID(), values.at(1));
334
335 factor = isPlus ? modes[i].ap : factor;
336 factor = isMinus ? modes[i].am : factor;
337 factor = isZero ? 1.0 : factor;
338
339 masterContribs[i] = factor * values.at(1);
340 }
341}
342
343int
344SolutionbasedShapeFunction :: giveNumberOfMasterDofs(ActiveDof *dof)
345{
346 return this->giveDomain()->giveNumberOfSpatialDimensions();
347}
348
349Dof *
350SolutionbasedShapeFunction :: giveMasterDof(ActiveDof *dof, int mdof)
351{
352 return myNode->giveDofWithID(myDofIDs.at(mdof));
353}
354
355void
356SolutionbasedShapeFunction :: loadProblem()
357{
358 for ( int i = 0; i < this->domain->giveNumberOfSpatialDimensions(); i++ ) {
359 OOFEM_LOG_INFO("************************** Instanciating microproblem from file %s for dimension %u\n", filename.c_str(), i);
360
361 // Set up and solve problem
362 OOFEMTXTDataReader drMicro( filename.c_str() );
363 auto myEngngModel = InstanciateProblem(drMicro, _processor, 0, NULL, false);
364 drMicro.finish();
365 myEngngModel->checkProblemConsistency();
366 myEngngModel->initMetaStepAttributes( myEngngModel->giveMetaStep(1) );
367 thisTimestep = myEngngModel->giveNextStep();
368 myEngngModel->init();
369 this->setLoads(*myEngngModel, i + 1);
370
371 // Check
372 for ( auto &elem : myEngngModel->giveDomain(1)->giveElements() ) {
373 FloatArray centerCoord;
374 int vlockCount = 0;
375 centerCoord.resize(3);
376 centerCoord.zero();
377
378 for ( int k = 1; k <= elem->giveNumberOfDofManagers(); k++ ) {
379 DofManager *dman = elem->giveDofManager(k);
380 centerCoord.add( dman->giveCoordinates() );
381 for ( Dof *dof: *dman ) {
382 if ( dof->giveBcId() != 0 ) {
383 vlockCount++;
384 }
385 }
386 }
387 if ( vlockCount == 30 ) {
388 OOFEM_WARNING("Element over-constrained (%u)! Center coordinate: %f, %f, %f\n", elem->giveNumber(), centerCoord.at(1) / 10, centerCoord.at(2) / 10, centerCoord.at(3) / 10);
389 }
390 }
391
392 myEngngModel->solveYourselfAt(thisTimestep);
393 isLoaded = true;
394
395 // Set correct export filename
396 std :: string originalFilename;
397 originalFilename = myEngngModel->giveOutputBaseFileName();
398
399 if (i==0) originalFilename = originalFilename + "_X";
400 if (i==1) originalFilename = originalFilename + "_Y";
401 if (i==2) originalFilename = originalFilename + "_Z";
402 if (dumpSnapshot) {
403 myEngngModel->letOutputBaseFileNameBe(originalFilename + "_1_Base");
404 myEngngModel->doStepOutput(thisTimestep);
405 }
406
407 modeStruct mode;
408 mode.myEngngModel = std::move(myEngngModel);
409
410 // Check elements
411
412 // Set unknowns to the mean value of opposite sides of the domain.
413 // Loop thru all nodes and compute phi for all degrees of freedom on the boundary. Save phi in a list for later use.
414
416 // Update with factor
417 double am=1.0, ap=1.0;
418
420 computeCorrectionFactors(mode, dofs, am, ap);
421 }
422
423 OOFEM_LOG_INFO("Correction factors: am=%f, ap=%f\n", am, ap);
424
425 mode.ap = ap;
426 mode.am = am;
427
429
430 if (dumpSnapshot) {
431 myEngngModel->letOutputBaseFileNameBe(originalFilename + "_2_Updated");
432 myEngngModel->doStepOutput(thisTimestep);
433 }
434
435 modes.push_back(std::move(mode));
436
437 OOFEM_LOG_INFO("Microproblem at instanciated\n");
438 }
439}
440
441void
442SolutionbasedShapeFunction :: updateModelWithFactors(modeStruct &m)
443{
444 //Update values with correction factors
445 for ( size_t j = 0; j < m.SurfaceData.size(); j++ ) {
446 SurfaceDataStruct &sd = m.SurfaceData.at(j);
447 DofManager &dman = *sd.DofMan;
448 Dof *d = dman.giveDofWithID(sd.DofID);
449
450 double factor = 1.0;
451 factor = sd.isPlus ? m.ap : factor;
452 factor = sd.isMinus ? m.am : factor;
453 factor = sd.isZeroBoundary ? 1.0 : factor;
454
455 if ( dynamic_cast< MasterDof * >(d) && sd.isFree ) {
456 double u = sd.value;
457 this->setBoundaryConditionOnDof(dman.giveDofWithID(sd.DofID), u * factor);
458 }
459 }
460}
461
462void
463SolutionbasedShapeFunction :: setLoads(EngngModel &myEngngModel, int d)
464{
466 FloatArray gradP;
467
468 gradP.resize( this->giveDomain()->giveNumberOfSpatialDimensions() );
469 gradP.zero();
470 gradP.at(d) = 1.0;
471
472 ir.setRecordKeywordField("deadweight", 1);
475
476 int bcID = myEngngModel.giveDomain(1)->giveNumberOfBoundaryConditions() + 1;
477 auto myBodyLoad = classFactory.createBoundaryCondition( "deadweight", bcID, myEngngModel.giveDomain(1) );
478 myBodyLoad->initializeFrom(ir);
479 myEngngModel.giveDomain(1)->setBoundaryCondition(bcID, std::move(myBodyLoad));
480
481 for ( auto &elem : myEngngModel.giveDomain(1)->giveElements() ) {
482 IntArray *blArray;
483 blArray = elem->giveBodyLoadArray();
484 blArray->resizeWithValues(blArray->giveSize() + 1);
485 blArray->at( blArray->giveSize() ) = bcID;
486 }
487}
488
489void
490SolutionbasedShapeFunction :: computeBaseFunctionValueAt(FloatArray &answer, const FloatArray &coords, IntArray &dofIDs, EngngModel &myEngngModel)
491{
492 answer.resize( dofIDs.giveSize() );
493 answer.zero();
494
495 if ( useConstantBase ) {
496 for ( int i = 1; i <= answer.giveSize(); i++ ) {
497 answer.at(i) = 1;
498 }
499 ;
500 } else {
501 std :: vector< FloatArray >checkcoords;
502 std :: vector< int >permuteIndex;
503 int n = 0;
504
505 if ( !isLoaded ) {
506 loadProblem();
507 }
508
509 myEngngModel.giveDomain(1)->giveSpatialLocalizer()->init(false);
510
511 if ( this->giveDomain()->giveNumberOfSpatialDimensions() == 2 ) {
512 //coords.resize(2); /// FIXME
513 }
514
515 // Determine if current coordinate is at a max or min point and if so, which type (on a surface, edge or a corner?)
516 // n is the number of dimensions at which the point is an extremum, permuteIndex tells in which dimension the coordinate is max/min
517
518 int thisMask = 0;
519
520 for ( int i = 1; i <= coords.giveSize(); i++ ) {
521 if ( ( fabs( maxCoord.at(i) - coords.at(i) ) < TOL ) || ( fabs( minCoord.at(i) - coords.at(i) ) < TOL ) ) {
522 permuteIndex.push_back(i);
523 n++;
524 //thisMask = thisMask + pow(2.0, i - 1); // compiler warning on conversion from double to int
525 thisMask = thisMask + ( 0x01 << ( i - 1 ) );
526 }
527 }
528 int _s = 0x01 << n;
529 for ( int i = 0; i < _s; i++ ) {
530 int mask = i, counter = 1;
531 FloatArray newCoord = coords;
532
533 for ( int j = 1; j <= n; j++ ) {
534 double d = 0.0; //TOL;
535 if ( ( mask & 1 ) == 0 ) { // Max
536 newCoord.at( permuteIndex.at(counter - 1) ) = minCoord.at( permuteIndex.at(counter - 1) ) + d;
537 } else { // Min
538 newCoord.at( permuteIndex.at(counter - 1) ) = maxCoord.at( permuteIndex.at(counter - 1) ) - d;
539 }
540 counter++;
541 mask = mask >> 1;
542 }
543 checkcoords.emplace_back(newCoord);
544 }
545
546 // The followind define allows for use of weakly periodic bc to be copied. This does not comply with the theory but is used to check the validity of the code.
547#define USEWPBC 0
548
549#if USEWPBC == 1
550 FloatArray *tempCoord = new FloatArray;
551 * tempCoord = coords;
552 checkcoords.clear();
553 checkcoords.push_back(tempCoord);
554#endif
555 FloatArray values;
556 for ( size_t i = 0; i < checkcoords.size(); i++ ) {
557 giveValueAtPoint(values, checkcoords[i], dofIDs, myEngngModel);
558 //printf("Values at (%f, %f, %f) are [%f, %f, %f]\n", checkcoords.at(i)->at(1), checkcoords.at(i)->at(2), checkcoords.at(i)->at(3), values.at(1), values.at(2), values.at(3));
559#if USEWPBC == 1
560 for ( int j = 1; j <= values.giveSize(); j++ ) {
561 answer.at(j) = values.at(j);
562 }
563#else
564 for ( int j = 1; j <= values.giveSize(); j++ ) {
565 answer.at(j) += values.at(j) / ( ( double ) pow(2.0, n) );
566 }
567#endif
568 }
569 }
570}
571
572void
573SolutionbasedShapeFunction :: giveValueAtPoint(FloatArray &answer, const FloatArray &coords, IntArray &dofIDs, EngngModel &myEngngModel)
574{
575 answer.resize( dofIDs.giveSize() );
576
577 FloatArray closest, lcoords, values;
578
579 Element *elementAtCoords = myEngngModel.giveDomain(1)->giveSpatialLocalizer()->giveElementClosestToPoint(lcoords, closest, coords, 1);
580 if ( elementAtCoords == NULL ) {
581 OOFEM_WARNING("Cannot find element closest to point");
582 coords.pY();
583 return;
584 }
585
586 IntArray eldofids;
587
588 elementAtCoords->giveElementDofIDMask(eldofids);
589 elementAtCoords->computeField(VM_Total, thisTimestep, lcoords, values);
590
591 for ( int i = 1; i <= dofIDs.giveSize(); i++ ) {
592 for ( int j = 1; j <= eldofids.giveSize(); j++ ) {
593 if ( dofIDs.at(i) == eldofids.at(j) ) {
594 answer.at(i) = values.at(j);
595 break;
596 }
597 }
598 }
599}
600
601void
602SolutionbasedShapeFunction :: setBoundaryConditionOnDof(Dof *d, double value)
603{
604 int bcID = d->giveBcId();
605
606 if ( bcID == 0 ) {
608 ir.setRecordKeywordField("boundarycondition", 1);
611
613
614 auto myBC = classFactory.createBoundaryCondition( "boundarycondition", bcID, d->giveDofManager()->giveDomain() );
615 myBC->initializeFrom(ir);
616 d->giveDofManager()->giveDomain()->setBoundaryCondition(bcID, std::move(myBC));
617
618 d->setBcId(bcID);
619 } else {
620 BoundaryCondition *bc = static_cast< BoundaryCondition * >( d->giveDofManager()->giveDomain()->giveBc(bcID) );
621 bc->setPrescribedValue(value);
622 }
623}
624
625void
626SolutionbasedShapeFunction :: initializeSurfaceData(modeStruct &mode)
627{
628
629 EngngModel &m = *mode.myEngngModel;
630 double TOL2 = 1e-3;
631
632 IntArray pNodes, mNodes, zNodes;
633
634 Set *mySet = this->domain->giveSet( this->giveSetNumber() );
635 IntArray BoundaryList = mySet->giveBoundaryList();
636
637 // First add all nodes to pNodes or nNodes respectively depending on coordinate and normal.
638 for ( int i = 0; i < BoundaryList.giveSize() / 2; i++ ) {
639 int ElementID = BoundaryList[2 * i];
640 int Boundary = BoundaryList[2 * i + 1];
641
642 Element *e = m.giveDomain(1)->giveElement(ElementID);
643 FEInterpolation *geoInterpolation = e->giveInterpolation();
644
645 // Check all sides of element
646#define usePoints 1
647#if usePoints == 1
648 // Check if all nodes are on the boundary
649 auto bnodes = geoInterpolation->boundaryGiveNodes(Boundary, e->giveGeometryType());
650 for ( int k = 1; k <= bnodes.giveSize(); k++ ) {
651 DofManager *dman = e->giveDofManager( bnodes.at(k) );
652 for ( int l = 1; l <= dman->giveCoordinates().giveSize(); l++ ) {
653 if ( fabs( dman->giveCoordinates().at(l) - maxCoord.at(l) ) < TOL2 ) {
654 pNodes.insertOnce( dman->giveNumber() );
655 }
656 if ( fabs( dman->giveCoordinates().at(l) - minCoord.at(l) ) < TOL2 ) {
657 mNodes.insertOnce( dman->giveNumber() );
658 }
659 }
660 }
661#else
662 // Check normal
663 FloatArray lcoords;
664 lcoords.resize(2);
665 lcoords.at(1) = 0.33333;
666 lcoords.at(2) = 0.33333;
667
668 FloatArray normal;
669 geoInterpolation->boundaryEvalNormal( normal, j, lcoords, FEIElementGeometryWrapper(e) );
670 geoInterpolation->boundaryGiveNodes(bnodes, j);
671
672 printf( "i=%u\tj=%u\t(%f\t%f\t%f)\n", i, j, normal.at(1), normal.at(2), normal.at(3) );
673 for ( int k = 1; k <= normal.giveSize(); k++ ) {
674 if ( fabs( ( fabs( normal.at(k) ) - 1 ) ) < 1e-4 ) { // Points in x, y or z direction
675 addTo = NULL;
676 if ( normal.at(k) > 0.5 ) {
677 addTo = & pNodes;
678 }
679 if ( normal.at(k) < -0.5 ) {
680 addTo = & mNodes;
681 }
682 if ( addTo != NULL ) {
683 for ( int l = 1; l <= bnodes.giveSize(); l++ ) {
684 bool isSurface = false;
685 DofManager *dman = e->giveDofManager( bnodes.at(l) );
687 for ( int m = 1; m <= dman->giveCoordinates()->giveSize(); m++ ) {
688 if ( ( fabs( dman->giveCoordinates()->at(m) - maxCoord.at(m) ) < TOL2 ) || ( fabs( dman->giveCoordinates()->at(m) - minCoord.at(m) ) < TOL2 ) ) {
689 isSurface = true;
690 }
691 }
692
693 if ( isSurface ) {
694 addTo->insertOnce( e->giveDofManagerNumber( bnodes.at(l) ) );
695 }
696 }
697 }
698 }
699 }
700#endif
701 }
702
703#if 0
704 printf("p=[");
705 for ( int i = 1; i < pNodes.giveSize(); i++ ) {
706 printf( "%u, ", pNodes.at(i) );
707 }
708 printf("];\n");
709 printf("m=[");
710 for ( int i = 1; i < mNodes.giveSize(); i++ ) {
711 printf( "%u, ", mNodes.at(i) );
712 }
713 printf("];\n");
714#endif
715 //The intersection of pNodes and mNodes constitutes zNodes
716 {
717 int i = 1, j = 1;
718 while ( i <= pNodes.giveSize() ) {
719 j = 1;
720 while ( j <= mNodes.giveSize() && ( i <= pNodes.giveSize() ) ) {
721 //printf("%u == %u?\n", pNodes.at(i), mNodes.at(j));
722 if ( pNodes.at(i) == mNodes.at(j) ) {
723 zNodes.insertOnce( pNodes.at(i) );
724 pNodes.erase(i);
725 mNodes.erase(j);
726 } else {
727 j++;
728 }
729 }
730 i++;
731 }
732 }
733
734 // Compute base function values on nodes for dofids
735 copyDofManagersToSurfaceData(mode, pNodes, true, false, false);
736 copyDofManagersToSurfaceData(mode, mNodes, false, true, false);
737 copyDofManagersToSurfaceData(mode, zNodes, false, false, true);
738
739#if 0
740 printf("p2=[");
741 for ( int i = 1; i <= pNodes.giveSize(); i++ ) {
742 printf( "%u, ", pNodes.at(i) );
743 }
744 printf("];\n");
745 printf("m2=[");
746 for ( int i = 1; i <= mNodes.giveSize(); i++ ) {
747 printf( "%u, ", mNodes.at(i) );
748 }
749 printf("];\n");
750 printf("z2=[");
751 for ( int i = 1; i <= zNodes.giveSize(); i++ ) {
752 printf( "%u, ", zNodes.at(i) );
753 }
754 printf("];\n");
755
756 printf("pCoords=[");
757 for ( int i = 1; i <= pNodes.giveSize(); i++ ) {
758 FloatArray *coords = m->giveDomain(1)->giveDofManager( pNodes.at(i) )->giveCoordinates();
759 printf( "%f, %f, %f; ", coords->at(1), coords->at(2), coords->at(3) );
760 }
761 printf("]\n");
762 printf("mCoords=[");
763 for ( int i = 1; i <= mNodes.giveSize(); i++ ) {
764 FloatArray *coords = m->giveDomain(1)->giveDofManager( mNodes.at(i) )->giveCoordinates();
765 printf( "%f, %f, %f; ", coords->at(1), coords->at(2), coords->at(3) );
766 }
767 printf("]\n");
768 printf("zCoords=[");
769 for ( int i = 1; i <= zNodes.giveSize(); i++ ) {
770 FloatArray *coords = m->giveDomain(1)->giveDofManager( zNodes.at(i) )->giveCoordinates();
771 printf( "%f, %f, %f; ", coords->at(1), coords->at(2), coords->at(3) );
772 }
773 printf("];\n");
774#endif
775}
776
777void
778SolutionbasedShapeFunction :: whichBoundary(const FloatArray &coord, bool &isPlus, bool &isMinus, bool &isZero)
779{
780 isPlus = false;
781 isMinus = false;
782 isZero = false;
783
784 for ( int k = 1; k <= coord.giveSize(); k++ ) {
785 isPlus = isPlus || ( fabs( coord.at(k) - maxCoord.at(k) ) < TOL );
786 isMinus = isMinus || ( fabs( coord.at(k) - minCoord.at(k) ) < TOL );
787 }
788
789 isZero = isPlus && isMinus;
790}
791
792void
793SolutionbasedShapeFunction :: copyDofManagersToSurfaceData(modeStruct &mode, IntArray nodeList, bool isPlus, bool isMinus, bool isZeroBoundary)
794{
795 for ( int i = 1; i <= nodeList.giveSize(); i++ ) {
796 FloatArray values;
797
798 IntArray DofIDs;
799 DofManager *dman = mode.myEngngModel->giveDomain(1)->giveDofManager(nodeList.at(i));
800
801 computeBaseFunctionValueAt(values, dman->giveCoordinates(), this->dofs, *mode.myEngngModel );
802
803 // Check that current node contains current DofID
804 for (int j=1; j<=this->dofs.giveSize(); j++) {
805 for (Dof *d: *dman ){ //int k=1; k<= dman->giveNumberOfDofs(); k++ ) {
806
807 //Dof *d = dman->dofArray.at(k);// giveDof(k);
808
809 if (d->giveDofID() == this->dofs.at(j)) {
810 SurfaceDataStruct surfaceData {
811 isPlus,
812 isMinus,
813 isZeroBoundary,
814 d->giveBcId() == 0,
815 (DofIDItem) this->dofs.at(j),
816 dman,
817 values.at(j),
818 };
819 mode.SurfaceData.emplace_back(std::move(surfaceData));
820 }
821 }
822 }
823 }
824}
825}
#define _IFT_BoundaryCondition_PrescribedValue
[rn,optional] Prescribed value of all DOFs
#define N(a, b)
#define REGISTER_BoundaryCondition(class)
const FloatArray & giveCoordinates() const
Definition dofmanager.h:390
Dof * giveDofWithID(int dofID) const
Definition dofmanager.C:127
DofIDItem giveDofID() const
Definition dof.h:276
DofManager * giveDofManager() const
Definition dof.h:123
virtual void setBcId(int bcId)
Overwrites the boundary condition id (0-inactive BC), intended for specific purposes such as coupling...
Definition dof.h:382
virtual int giveBcId()=0
SpatialLocalizer * giveSpatialLocalizer()
Definition domain.C:1255
int giveNumberOfBoundaryConditions() const
Returns number of boundary conditions in domain.
Definition domain.h:469
Set * giveSet(int n)
Definition domain.C:366
DofManager * giveDofManager(int n)
Definition domain.C:317
Element * giveElement(int n)
Definition domain.C:165
void setBoundaryCondition(int i, std::unique_ptr< GeneralBoundaryCondition > obj)
Sets i-th component. The component will be further managed and maintained by domain object.
Definition domain.C:471
std ::vector< std ::unique_ptr< Element > > & giveElements()
Definition domain.h:294
void setRecordKeywordField(std ::string keyword, int number)
void setField(int item, InputFieldType id)
virtual void giveElementDofIDMask(IntArray &answer) const
Definition element.h:510
virtual FEInterpolation * giveInterpolation() const
Definition element.h:648
DofManager * giveDofManager(int i) const
Definition element.C:553
int giveDofManagerNumber(int i) const
Definition element.h:609
virtual void computeField(ValueModeType mode, TimeStep *tStep, const FloatArray &lcoords, FloatArray &answer)
Definition element.h:520
virtual Element_Geometry_Type giveGeometryType() const =0
Domain * giveDomain(int n)
Definition engngm.C:1936
virtual std::unique_ptr< IntegrationRule > giveBoundaryIntegrationRule(int order, int boundary, const Element_Geometry_Type) const
Definition feinterpol.C:101
virtual IntArray boundaryGiveNodes(int boundary, const Element_Geometry_Type) const =0
virtual double boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const =0
virtual void boundaryLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const =0
virtual double boundaryEvalNormal(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const =0
virtual void boundaryEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const =0
Domain * giveDomain() const
Definition femcmpnn.h:97
Domain * domain
Link to domain object, useful for communicating with other FEM components.
Definition femcmpnn.h:79
int giveNumber() const
Definition femcmpnn.h:104
void resize(Index s)
Definition floatarray.C:94
virtual void pY() const
Definition floatarray.C:802
double & at(Index i)
Definition floatarray.h:202
double dotProduct(const FloatArray &x) const
Definition floatarray.C:524
Index giveSize() const
Returns the size of receiver.
Definition floatarray.h:261
virtual void printYourself() const
Definition floatarray.C:762
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
void add(const FloatArray &src)
Definition floatarray.C:218
void resize(Index rows, Index cols)
Definition floatmatrix.C:79
void zero()
Zeroes all coefficient of receiver.
double at(std::size_t i, std::size_t j) const
IntArray dofs
Dofs that b.c. is applied to (relevant for Dirichlet type b.c.s).
void insertSorted(int value, int allocChunk=0)
Definition intarray.C:299
void resizeWithValues(int n, int allocChunk=0)
Definition intarray.C:64
void insertOnce(int p)
Definition intarray.C:361
void erase(int pos)
Definition intarray.C:112
int & at(std::size_t i)
Definition intarray.h:104
int giveSize() const
Definition intarray.h:211
const IntArray & giveBoundaryList()
Definition set.C:160
void computeCorrectionFactors(modeStruct &myMode, IntArray &Dofs, double &am, double &ap)
void giveValueAtPoint(FloatArray &answer, const FloatArray &coords, IntArray &dofID, EngngModel &myEngngModel)
giveValueAtPoint
void setLoads(EngngModel &myEngngModel, int d)
void computeBaseFunctionValueAt(FloatArray &answer, const FloatArray &coords, IntArray &dofIDs, EngngModel &myEngngModel)
void computeDofTransformation(ActiveDof *dof, FloatArray &masterContribs) override
void copyDofManagersToSurfaceData(modeStruct &mode, IntArray nodeList, bool isPlus, bool isMinus, bool isZero)
double giveUnknown(PrimaryField &field, ValueModeType mode, TimeStep *tStep, ActiveDof *dof) override
void splitBoundaryNodeIDs(modeStruct &mode, Element &e, IntArray &boundary, IntArray &pList, IntArray &mList, IntArray &zList, FloatMatrix &nodeValues)
void setBoundaryConditionOnDof(Dof *d, double value)
void whichBoundary(const FloatArray &coord, bool &isPlus, bool &isMinus, bool &isZero)
virtual int init(bool force=false)
virtual Element * giveElementClosestToPoint(FloatArray &lcoords, FloatArray &closest, const FloatArray &coords, int region=0)=0
#define OOFEM_WARNING(...)
Definition error.h:80
#define OOFEM_ERROR(...)
Definition error.h:79
#define _IFT_GeneralBoundaryCondition_timeFunct
#define IR_GIVE_OPTIONAL_FIELD(__ir, __value, __id)
Definition inputrecord.h:75
#define TOL
#define _IFT_Load_components
Definition load.h:47
#define OOFEM_LOG_INFO(...)
Definition logger.h:143
FloatArrayF< N > min(const FloatArrayF< N > &a, const FloatArrayF< N > &b)
FloatArrayF< N > max(const FloatArrayF< N > &a, const FloatArrayF< N > &b)
std::unique_ptr< EngngModel > InstanciateProblem(DataReader &dr, problemMode mode, int contextFlag, EngngModel *_master, bool parallelFlag)
Definition util.C:153
void logDataMsg(const char *c, T myArray)
ClassFactory & classFactory
void logData(T myArray)
@ _processor
Definition problemmode.h:40
#define _IFT_SolutionbasedShapeFunction_DumpSnapshots
#define _IFT_SolutionbasedShapeFunction_Externalset
#define _IFT_SolutionbasedShapeFunction_ShapeFunctionFile
#define _IFT_SolutionbasedShapeFunction_UseCorrectionFactors
std::unique_ptr< EngngModel > myEngngModel
std ::vector< SurfaceDataStruct > SurfaceData

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