OOFEM 3.0
Loading...
Searching...
No Matches
quasicontinuum.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; eitherc
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
37#include "qcnode.h"
38#include "element.h"
39#include "mathfem.h"
40
41#include "classfactory.h"
42#include "dynamicinputrecord.h"
46#include "interfacetype.h"
48
49
50namespace oofem {
51//REGISTER_Quasicontinuum(QCFullsolveddomain);
52
53Quasicontinuum :: Quasicontinuum()
54{}
55
56
57Quasicontinuum :: ~Quasicontinuum()
58{}
59
60
61void
62Quasicontinuum :: setNoDimensions(Domain *d)
63// rewrite existing interpolation mesh
64{
65 int dim = d->giveNumberOfSpatialDimensions();
66 if ( dim == 2 || dim == 3 ) {
67 this->nDimensions = dim;
68 } else {
69 OOFEM_ERROR("Invalid number of dimensions. Only 2d and 3d domains are supported in QC simulation. \n");
70 }
71}
72
73
74void
75Quasicontinuum :: setupInterpolationMesh(Domain *d, int generateInterpolationElements, int interpolationElementsMaterialNumber, std :: vector< IntArray > &newMeshNodes)
76// rewrite existing interpolation mesh
77{
78 int noNewEl = 0;
79 if ( generateInterpolationElements == 0 ) {
80 // nodes are not needed
81 this->interpolationMeshNodes.clear();
82 // elements are defined in imput file by material number
83 this->interpolationElementNumbers = d->giveElementsWithMaterialNum(interpolationElementsMaterialNumber);
84 } else if ( ( generateInterpolationElements == 1 ) || ( generateInterpolationElements == 2 ) ) {
85 // nodes were (generated and ) loaded from t3d output file
86 this->interpolationMeshNodes = newMeshNodes;
87 // elements will be placed in the end of element list
88 this->interpolationElementNumbers.clear();
89 int noEl = d->giveNumberOfElements();
90 noNewEl = newMeshNodes.size();
91 this->interpolationElementNumbers.resize(noNewEl);
92 for ( int i = 1; i <= noNewEl; i++ ) {
93 this->interpolationElementNumbers.at(i) = noEl + i;
94 }
95 } else {
96 OOFEM_ERROR("Invalid input field \"GenInterpElem\". Value: %d is not supported", generateInterpolationElements);
97 }
98
100 for ( int i = 1; i <= interpolationElementNumbers.giveSize(); i++ ) {
102 }
103}
104
105
106void
107Quasicontinuum :: createInterpolationElements(Domain *d)
108// create new elements. Material will be defined after post initialization
109{
110 /*
111 * // new crosssection
112 * int ncrosssect = d->giveNumberOfCrossSectionModels() + 1;
113 * d->resizeCrossSectionModels(ncrosssect);
114 * CrossSection *crossSection;
115 * crossSection = classFactory.createCrossSection("SimpleCS", ncrosssect, d);
116 * DynamicInputRecord irCS;
117 * irCS.setField(1.0, _IFT_SimpleCrossSection_thick);
118 * irCS.setField(1.0, _IFT_SimpleCrossSection_width);
119 * crossSection->initializeFrom(&irCS);
120 * d->setCrossSection(ncrosssect, crossSection);
121 */
122
123 int ninterpelem = interpolationMeshNodes.size();
124
125 /*
126 * #if DEBUG
127 * if (ninterpelem==0) {
128 * OOFEM_WARNING("No interpolation elements generated");
129 * }
130 * #endif
131 */
132
133 // add interpolation elements (with new CS and no mat)
134 if ( interpolationMeshNodes.size() != 0 ) {
135 // for 2d
136 const char *elemType;
137 if ( nDimensions == 2 ) {
138 //elemType = "TrPlaneStrain";
139 elemType = "TrPlaneStress2d";
140 //for 3d
141 } else {
142 elemType = "LTRSpace";
143 }
144
145 int nelem = d->giveNumberOfElements();
147 // over interpolation elements
148 for ( int i = 1; i <= ninterpelem; i++ ) {
149 int elemNumber = nelem + i;
150 d->resizeElements(elemNumber);
151 auto elem = classFactory.createElement(elemType, elemNumber, d);
152 irEl.setField(interpolationMeshNodes [ i - 1 ], Element::IPK_Element_nodes.getNameCStr());
153 //irEl.setField( ncrosssect, _IFT_Element_crosssect);
154 //irEl.setField( nmat, _IFT_Element_mat);
155 elem->initializeFrom(irEl, 1);
156 elem->setGlobalNumber(elemNumber);
157 d->setElement(elemNumber, std::move(elem));
158 }
159 }
160}
161
162
163void
164Quasicontinuum :: addCrosssectionToInterpolationElements(Domain *d)
165{
166 // new crosssection
167 int ncrosssect = d->giveNumberOfCrossSectionModels() + 1;
168 d->resizeCrossSectionModels(ncrosssect);
169 auto crossSection = classFactory.createCrossSection("SimpleCS", ncrosssect, d);
173 crossSection->initializeFrom(irCS);
174 d->setCrossSection(ncrosssect, std::move(crossSection));
175
176 for ( int i = 1; i <= interpolationElementNumbers.giveSize(); i++ ) {
177 int elNum = interpolationElementNumbers.at(i);
178 d->giveElement(elNum)->setCrossSection(ncrosssect);
179 }
180}
181
182
183void
184Quasicontinuum :: applyApproach1(Domain *d)
185// Approach 1 --- Hangingnodes (interpolation elementss with zero stiffnes)
186{
187 // new material with zero stiffness
188 int nmat = d->giveNumberOfMaterialModels() + 1;
189 d->resizeMaterials(nmat);
190 auto mat = classFactory.createMaterial("IsoLE", nmat, d);
191 DynamicInputRecord irMat;
196 mat->initializeFrom(irMat);
197 d->setMaterial(nmat, std::move(mat));
198
199
200 // add material and CS to interpolation elements
201 int ninterpelem = interpolationElementNumbers.giveSize();
202 int matNum = nmat;
203 // over interpolation elements
204 for ( int i = 1; i <= ninterpelem; i++ ) {
205 int elNum = interpolationElementNumbers.at(i);
206 d->giveElement(elNum)->setMaterial(matNum);
207 }
208}
209
210
211void
212Quasicontinuum :: applyApproach2(Domain *d, int homMtrxType, double volumeOfInterpolationMesh)
213// Approach 2 --- Global homogenization
214{
215 // decision which links will solved explicitly/homogenized
216 elemList.resize( d->giveNumberOfElements() );
217 elemList.zero();
218 nodeList.resize( d->giveNumberOfDofManagers() );
219 nodeList.zero();
220
221 // ovel all elements // TO DO improve by using list of links only
222 for ( int i = 1; i <= d->giveNumberOfElements(); i++ ) {
223 if ( d->giveElement(i)->giveNumberOfNodes() > 2 ) {
224 elemList.at(i) = 1; // all interpolation elements will be active
225 continue; // skip interpolation elements
226 }
227
228 Element *e = d->giveElement(i);
229 int n1 = e->giveNode(1)->giveQcNodeType();
230 int n2 = e->giveNode(2)->giveQcNodeType();
231 // repnode--repnode - save link to elemList
232 if ( ( n1 == 1 ) && ( n2 == 1 ) ) {
233 elemList.at(i) = 1;
234 nodeList.at( e->giveNode(1)->giveNumber() ) = 1;
235 nodeList.at( e->giveNode(2)->giveNumber() ) = 1;
236
237 // hanging--hanging
238 } else if ( ( n1 == 2 ) && ( n2 == 2 ) ) {
239 // nothing to store, link will be homogenized-removed
240 // eventualy, link with end/ends outside intero element can be solved explicitly
241
242 // repnode--hanging
243 } else if ( ( n1 == 1 ) && ( n2 == 2 ) ) {
244 int mn = e->giveNode(1)->giveNumber();
245 int hn = e->giveNode(2)->giveNumber();
246 qcNode *qn = static_cast< qcNode * >( e->giveNode(2) );
247 int masterElem = qn->giveMasterElementNumber();
248 IntArray nodesOfMasterElem = d->giveElement(masterElem)->giveDofManArray();
249 // is masterNode one of nodes of master element?
250 if ( !nodesOfMasterElem.contains(mn) ) { // master node is not vertex of hn master elements
251 elemList.at(i) = 1;
252 nodeList.at(mn) = 1;
253 nodeList.at(hn) = 1;
254 } else {
255 // nothing to store, link will be homogenized-removed
256 }
257
258 // hanging--repnode
259 } else if ( ( n1 == 2 ) && ( n2 == 1 ) ) {
260 int mn = e->giveNode(2)->giveNumber();
261 int hn = e->giveNode(1)->giveNumber();
262 qcNode *n = static_cast< qcNode * >( e->giveNode(1) );
263 int masterElem = n->giveMasterElementNumber();
264 IntArray nodesOfMasterElem = d->giveElement(masterElem)->giveDofManArray();
265 // is masterNode one of nodes of master element?
266 if ( !nodesOfMasterElem.contains(mn) ) { // master node is not vertex of hn master elements
267 elemList.at(i) = 1;
268 nodeList.at(mn) = 1;
269 nodeList.at(hn) = 1;
270 } else {
271 // nothing to store, link will be homogenized-removed
272 }
273
274
275 // no QcNode
276 } else {
277 OOFEM_WARNING("Element %d with non-qcNode can not be homogenized", i);
278 elemList.at(i) = 1;
279 nodeList.at( e->giveNode(1)->giveNumber() ) = 1;
280 nodeList.at( e->giveNode(2)->giveNumber() ) = 1;
281 }
282 } // ovel all links
283
284
285 /* // qcRenumbering ir realized instead of this...
286 * // deactivate homogenized nodes
287 * for (int i=1; i<=d->giveNumberOfDofManagers(); i++) {
288 * if ( !nodeList(i) ) {
289 * /// d->giveNode(i)->deactivateYourself();
290 * }
291 * }
292 *
293 * // deactivate homogenized elements
294 * for (int i=1; i<=d->giveNumberOfElements(); i++) {
295 * if ( !elemList(i) ) {
296 * /// d->giveElement(i)->deactivateYourself();
297 * }
298 * }
299 */
300
301 // set up lists of active nodes and elements
302 QClinearStatic *em = dynamic_cast< QClinearStatic * >( d->giveEngngModel() );
303 if ( em ) {
306 } else {
307 OOFEM_ERROR("Quasicontinuum can be applied only in QClinearStatic engngm");
308 }
309
310
311 // global homogenization
312 double S0;
313 FloatMatrix Diso(6, 6);
314 createGlobalStiffnesMatrix(Diso, S0, d, homMtrxType, volumeOfInterpolationMesh);
315
316 double homogenizedE, homogenizedNu;
317 homogenizationOfStiffMatrix(homogenizedE, homogenizedNu, Diso);
318
319
320 // new material with homogenized stiffness
321 int nmat = d->giveNumberOfMaterialModels() + 1;
322 d->resizeMaterials(nmat);
323 std::unique_ptr<Material> mat;
324 DynamicInputRecord irMat;
325 // isotropic
326 if ( homMtrxType == 1 ) {
327 mat = classFactory.createMaterial("IsoLE", nmat, d);
332 // anisotropic
333 } else if ( homMtrxType == 2 ) {
334 //OOFEM_ERROR("anisotropic homog. is not inmplemented yet");
335 mat = classFactory.createMaterial("AnisoLE", nmat, d);
336 FloatArray stiff;
337 //FloatArray alpha(6);
338 //alpha.zero();
339 if ( nDimensions == 2 ) {
340 stiff = VecX({
341 Diso.at(1, 1), Diso.at(1, 2), 0, 0, 0, Diso.at(1, 6), \
342 Diso.at(2, 2), 0, 0, 0, Diso.at(2, 6), 33, 0, 0, 0, 44, \
343 0, 0, 55, 0, Diso.at(6, 6)
344 });
345 } else if ( nDimensions == 3 ) {
346 stiff = VecX({
347 Diso.at(1, 1), Diso.at(1, 2), Diso.at(1, 3), Diso.at(1, 4), Diso.at(1, 5), Diso.at(1, 6), \
348 Diso.at(2, 2), Diso.at(2, 3), Diso.at(2, 4), Diso.at(2, 5), Diso.at(2, 6), \
349 Diso.at(3, 3), Diso.at(3, 4), Diso.at(3, 5), Diso.at(3, 6), \
350 Diso.at(4, 4), Diso.at(4, 5), Diso.at(4, 6), \
351 Diso.at(5, 5), Diso.at(5, 6), Diso.at(6, 6)
352 });
353 } else {
354 OOFEM_ERROR("Invalid number of dimensions. Only 2d and 3d domains are supported in QC simulation. \n");
355 }
357 //irMat.setField(alpha, _IFT_AnisotropicLinearElasticMaterial_talpha);
359 } else {
360 OOFEM_ERROR("Invalid homMtrxType");
361 }
362 mat->initializeFrom(irMat);
363 d->setMaterial(nmat, std::move(mat));
364
365
366 // add material to interpolation elements
367 int ninterpelem = interpolationElementNumbers.giveSize();
368 int matNum = nmat;
369 // over interpolation elements
370 for ( int i = 1; i <= ninterpelem; i++ ) {
371 int elNum = interpolationElementNumbers.at(i);
372 d->giveElement(elNum)->setMaterial(matNum);
373 }
374}
375
376
377void
378Quasicontinuum :: applyApproach3(Domain *d, int homMtrxType)
379// Approach 3 --- Local homogenization (for each element individually)
380{
382
383 // decision which links will solved explicitly/homogenized
384 elemList.resize( d->giveNumberOfElements() );
385 elemList.zero();
386 nodeList.resize( d->giveNumberOfDofManagers() );
387 nodeList.zero();
388
389 bool stiffnesAssigned = false;
390 FloatMatrix stfTensorOf1Link(9, 9);
391 double s0Of1Link;
392
393 int noIntEl = interpolationElementNumbers.giveSize();
394 std :: vector< FloatMatrix > individualStiffnessMatrices;
395 std :: vector< FloatMatrix > individualStiffnessTensors;
396 individualStiffnessMatrices.resize(noIntEl, FloatMatrix(6, 6));
397 individualStiffnessTensors.resize(noIntEl, FloatMatrix(9, 9));
398
399 FloatArray individualS0;
400 individualS0.resize(noIntEl);
401 individualS0.zero();
402
403
404 // ovel all elements // TO DO improve by using list of links only
405 for ( int i = 1; i <= d->giveNumberOfElements(); i++ ) {
406 if ( d->giveElement(i)->giveNumberOfNodes() > 2 ) {
407 elemList.at(i) = 1; // all interpolation elements will be active
408 continue; // skip interpolation elements
409 }
410
411 Element *e = d->giveElement(i);
412 int n1 = e->giveNode(1)->giveQcNodeType();
413 int n2 = e->giveNode(2)->giveQcNodeType();
414 // repnode--repnode - save link to elemList
415 if ( ( n1 == 1 ) && ( n2 == 1 ) ) {
416 elemList.at(i) = 1;
417 nodeList.at( e->giveNode(1)->giveNumber() ) = 1;
418 nodeList.at( e->giveNode(2)->giveNumber() ) = 1;
419
420 // hanging--hanging
421 } else if ( ( n1 == 2 ) && ( n2 == 2 ) ) {
422 // one or both ends ale not located outside interpolation elements
423 // link will be solved explicitly
424 qcNode *qn1 = static_cast< qcNode * >( e->giveNode(1) );
425 qcNode *qn2 = static_cast< qcNode * >( e->giveNode(2) );
426 int mn = e->giveNode(1)->giveNumber();
427 int hn = e->giveNode(2)->giveNumber();
428 if ( qn1->giveMasterElementNumber() < 0 || qn2->giveMasterElementNumber() < 0 ) {
429 elemList.at(i) = 1;
430 nodeList.at(mn) = 1;
431 nodeList.at(hn) = 1;
432 }
433 // both end are inside interp. elements
434 // link will be homogenized
435 else {
436 stiffnesAssigned = false;
437 stiffnesAssigned = stiffnessAssignment(individualStiffnessTensors, individualS0, d, e, qn1, qn2);
438 // stiffnesAssigned = stiffnessAssignment( individualStiffnessTensors, individualS0 );
439 if ( !stiffnesAssigned ) {
440 // stiffness of this link was no successfully asigned to interpolation elements - link will be solved explicitly
441 elemList.at(i) = 1;
442 nodeList.at(mn) = 1;
443 nodeList.at(hn) = 1;
444 }
445 }
446
447 // repnode--hanging
448 } else if ( ( n1 == 1 ) && ( n2 == 2 ) ) {
449 int mn = e->giveNode(1)->giveNumber();
450 int hn = e->giveNode(2)->giveNumber();
451 qcNode *qn = static_cast< qcNode * >( e->giveNode(2) );
452 int masterElem = qn->giveMasterElementNumber();
453 IntArray nodesOfMasterElem = d->giveElement(masterElem)->giveDofManArray();
454 // is masterNode one of nodes of master element?
455 if ( !nodesOfMasterElem.contains(mn) ) { // master node is not vertex of hn master elements
456 elemList.at(i) = 1;
457 nodeList.at(mn) = 1;
458 nodeList.at(hn) = 1;
459 } else {
460 // stiffness of link is assigned to masterElement
461 computeStiffnessTensorOf1Link(stfTensorOf1Link, s0Of1Link, e, d);
462 individualStiffnessTensors [ interpolationElementIndices.at(masterElem) - 1 ].add(stfTensorOf1Link);
463 individualS0 [ interpolationElementIndices.at(masterElem) - 1 ] += s0Of1Link;
464 }
465
466 // hanging--repnode
467 } else if ( ( n1 == 2 ) && ( n2 == 1 ) ) {
468 int mn = e->giveNode(2)->giveNumber();
469 int hn = e->giveNode(1)->giveNumber();
470 qcNode *n = static_cast< qcNode * >( e->giveNode(1) );
471 int masterElem = n->giveMasterElementNumber();
472 IntArray nodesOfMasterElem = d->giveElement(masterElem)->giveDofManArray();
473 // is masterNode one of nodes of master element?
474 if ( !nodesOfMasterElem.contains(mn) ) { // master node is not vertex of hn master elements
475 elemList.at(i) = 1;
476 nodeList.at(hn) = 1;
477 nodeList.at(mn) = 1;
478 } else {
479 // stiffness of link is assigned to masterElement
480 computeStiffnessTensorOf1Link(stfTensorOf1Link, s0Of1Link, e, d);
481 individualStiffnessTensors [ interpolationElementIndices.at(masterElem) - 1 ].add(stfTensorOf1Link);
482 individualS0 [ interpolationElementIndices.at(masterElem) - 1 ] += s0Of1Link;
483 }
484
485
486 // no QcNode
487 } else {
488 OOFEM_WARNING("Element %d with non-qcNode can not be homogenized", i);
489 elemList.at(i) = 1;
490 nodeList.at( e->giveNode(1)->giveNumber() ) = 1;
491 nodeList.at( e->giveNode(2)->giveNumber() ) = 1;
492 }
493 } // ovel all links
494
495
496 // convert stiffness tensors to stiff matrices and divide by volume of element
497 double volumeofEl, th;
498 for ( int i = 1; i <= noIntEl; i++ ) {
499 transformStiffnessTensorToMatrix(individualStiffnessMatrices [ i - 1 ], individualStiffnessTensors [ i - 1 ]);
501 if ( d->giveNumberOfSpatialDimensions() == 2 ) {
503 volumeofEl = volumeofEl / th;
504 }
505 individualStiffnessMatrices [ i - 1 ].times(1 / volumeofEl);
506 }
507 // ...
508
509
510 // deactivate homogenized nodes
511 for ( int i = 1; i <= d->giveNumberOfDofManagers(); i++ ) {
512 if ( !nodeList.at(i) ) {
513 // d->giveNode(i)->deactivateYourself();
514 }
515 }
516
517 // deactivate homogenized elements
518 for ( int i = 1; i <= d->giveNumberOfElements(); i++ ) {
519 if ( !elemList.at(i) ) {
520 // d->giveElement(i)->deactivateYourself();
521 }
522 }
523
524 // set up lists of active nodes and elements
525 QClinearStatic *em = dynamic_cast< QClinearStatic * >( d->giveEngngModel() );
526 if ( em ) {
529 } else {
530 OOFEM_ERROR("Quasicontinuum can be applied only in QClinearStatic engngm");
531 }
532
533
534 // new materials with homogenized stiffness
535 int originalNumberOfMaterials = d->giveNumberOfMaterialModels();
536 d->resizeMaterials(originalNumberOfMaterials + noIntEl);
537 int nmat = originalNumberOfMaterials;
538 DynamicInputRecord irMat;
539
540 // isotropic
541 if ( homMtrxType == 1 ) {
542 double homogenizedE, homogenizedNu;
543 for ( int i = 1; i <= noIntEl; i++ ) {
544 nmat++;
545 homogenizationOfStiffMatrix(homogenizedE, homogenizedNu, individualStiffnessMatrices [ i - 1 ]);
546 auto mat = classFactory.createMaterial("IsoLE", nmat, d);
551
552 mat->initializeFrom(irMat);
553 d->setMaterial(nmat, std::move(mat));
554 }
555
556 // anisotropic
557 } else if ( homMtrxType == 2 ) {
558 for ( int i = 1; i <= noIntEl; i++ ) {
559 FloatMatrix &Da = individualStiffnessMatrices [ i - 1 ];
560 nmat++;
561 auto mat = classFactory.createMaterial("AnisoLE", nmat, d);
562 FloatArray stiff;
563 // FloatArray alpha(6);
564 if ( nDimensions == 2 ) {
565 stiff = VecX({
566 Da.at(1, 1), Da.at(1, 2), 0, 0, 0, Da.at(1, 6), \
567 Da.at(2, 2), 0, 0, 0, Da.at(2, 6), 33, 0, 0, 0, 44, \
568 0, 0, 55, 0, Da.at(6, 6)
569 });
570 } else if ( nDimensions == 3 ) {
571 stiff = VecX({
572 Da.at(1, 1), Da.at(1, 2), Da.at(1, 3), Da.at(1, 4), Da.at(1, 5), Da.at(1, 6), \
573 Da.at(2, 2), Da.at(2, 3), Da.at(2, 4), Da.at(2, 5), Da.at(2, 6), \
574 Da.at(3, 3), Da.at(3, 4), Da.at(3, 5), Da.at(3, 6), \
575 Da.at(4, 4), Da.at(4, 5), Da.at(4, 6), \
576 Da.at(5, 5), Da.at(5, 6), Da.at(6, 6)
577 });
578 } else {
579 OOFEM_ERROR("Invalid number of dimensions. Only 2d and 3d domains are supported in QC simulation. \n");
580 }
582 // irMat.setField(alpha, _IFT_AnisotropicLinearElasticMaterial_talpha);
584
585 mat->initializeFrom(irMat);
586 d->setMaterial(nmat, std::move(mat));
587 }
588 } else {
589 OOFEM_ERROR("Invalid homMtrxType");
590 }
591
592
593 // add material to interpolation elements
594 int elNum;
595 int matNum = originalNumberOfMaterials;
596 // over interpolation elements
597 for ( int i = 1; i <= noIntEl; i++ ) {
598 matNum++;
599 elNum = interpolationElementNumbers.at(i);
600 d->giveElement(elNum)->setMaterial(matNum);
601 }
602}
603
604
605void
606Quasicontinuum :: homogenizationOfStiffMatrix(double &homogenizedE, double &homogenizedNu, const FloatMatrix &Diso)
607// identification of E and Nu from isotropic stiffness matrix
608{
609 // for 2d (planme stress only)
610 if ( this->nDimensions == 2 ) {
611 double a = Diso.at(1, 1);
612 double b = Diso.at(1, 2);
613 double d = Diso.at(2, 2);
614 double f = Diso.at(6, 6); // xy stiff is in last column
615 // Norma A - using eigen vectors - not implemented in 3D
616 if ( 33 * a + 2 * b + 33 * d + 4 * f == 0 ) { // zero matrix = empty interpolation element -> zero stiffness
617 homogenizedE = 1.0e-20;
618 homogenizedNu = 0;
619 } else {
620 homogenizedE = 4 * ( a + 2 * b + d ) * ( 4 * a - 8 * b + 4 * d + f ) / ( 33 * a + 2 * b + 33 * d + 4 * f );
621 homogenizedNu = ( a + 66 * b + d - 4 * f ) / ( 33 * a + 2 * b + 33 * d + 4 * f );
622 }
623 // Norma B - sum of squares of differences (with weight functions)
624 /*
625 * if (3*a+12*b+3*d==0) {// zero matrix = empty interpolation element -> zero stiffness
626 * homogenizedE = 1.0e-20;
627 * homogenizedNu = 0;
628 * } else {
629 * homogenizedE = (a+2*b+d)*(a+14*b+d)/2/(3*a+12*b+3*d);
630 * homogenizedNu = 2*(a-b+d)/(3*a+12*b+3*d);
631 * }
632 */
633
634 //for 3d
635 } else if ( this->nDimensions == 3 ) {
636 // Norma A - using eigen vectors
637 //- not implemented in 3D
638
639 // Norma B - sum of squares of differences (with weight functions)
640 double a = Diso.at(1, 1) + Diso.at(2, 2) + Diso.at(3, 3);
641 double b = Diso.at(4, 4) + Diso.at(5, 5) + Diso.at(6, 6);
642
643 if ( 5 * a + 13 * b == 0 ) { // zero matrix = empty interpolation element -> zero stiffness
644 homogenizedE = 1.0e-20;
645 homogenizedNu = 0;
646 } else {
647 homogenizedE = ( a + 2 * b ) * ( a + 11 * b ) / ( 15 * a + 39 * b );
648 homogenizedNu = ( 2 * a + b ) / ( 5 * a + 13 * b );
649 }
650 } else {
651 OOFEM_ERROR("Invalid number of dimensions. Only 2d and 3d domains are supported in QC simulation. \n");
652 }
653}
654
655
656void
657Quasicontinuum :: computeStiffnessTensorOf1Link(FloatMatrix &D1, double &S0, Element *e, Domain *d)
658{
659 // stiffness tensor 3^4 of 1 link represented by 9x9 mtrx
660 D1.resize(9, 9);
661 D1.zero();
662
663 S0 = 0.;
664
666 if ( !qcmei ) {
667 OOFEM_ERROR("Material doesn't implement the required QC interface!");
668 }
669 double Etruss = qcmei->giveQcElasticParamneter();
670 double Ry = qcmei->giveQcPlasticParamneter();
671
672 double area = 0.;
673 SimpleCrossSection *cs = dynamic_cast< SimpleCrossSection * >( e->giveCrossSection() );
674 if ( cs ) {
675 area = cs->give(CS_Area, NULL);
676 } else {
677 OOFEM_ERROR( "Invalid CrossSection of link %d. simpleCS is only supported CS of links in QC simulation. \n", e->giveGlobalNumber() );
678 }
679
680 double x1 = e->giveDofManager(1)->giveCoordinate(1);
681 double y1 = e->giveDofManager(1)->giveCoordinate(2);
682 double z1 = e->giveDofManager(1)->giveCoordinate(3);
683 double x2 = e->giveDofManager(2)->giveCoordinate(1);
684 double y2 = e->giveDofManager(2)->giveCoordinate(2);
685 double z2 = e->giveDofManager(2)->giveCoordinate(3);
686 double TrussLength = sqrt( ( x2 - x1 ) * ( x2 - x1 ) + ( y2 - y1 ) * ( y2 - y1 ) + ( z2 - z1 ) * ( z2 - z1 ) );
687 double n [ 3 ];
688 n [ 0 ] = ( x2 - x1 ) / TrussLength;
689 n [ 1 ] = ( y2 - y1 ) / TrussLength;
690 n [ 2 ] = ( z2 - z1 ) / TrussLength;
691 // create stiffness tensor
692 for ( int i = 1; i <= 3; i++ ) {
693 for ( int j = 1; j <= 3; j++ ) {
694 for ( int k = 1; k <= 3; k++ ) {
695 for ( int l = 1; l <= 3; l++ ) {
696 D1.at(3 * ( i - 1 ) + k, 3 * ( j - 1 ) + l) = TrussLength * Etruss * n [ i - 1 ] * n [ j - 1 ] * n [ k - 1 ] * n [ l - 1 ];
697 }
698 }
699 }
700 }
701
702 // homogenized yeld limit
703 if ( !std :: isinf(Ry) ) {
704 S0 += TrussLength * area * Ry / 3;
705 }
706}
707
708
709void
710Quasicontinuum :: createGlobalStiffnesMatrix(FloatMatrix &D, double &S0, Domain *d, int homMtrxType, double volumeOfInterpolationMesh)
711{
712 int noe = d->giveNumberOfElements();
713
714 S0 = 0;
715 //double StiffessTensor[81]; // stiffness tensor 3^4 represented by 9x9 mtrx
716 FloatMatrix StiffnessTensor(9, 9);
717
718 //double D1[81]; // stiffness tensor 3^4 of 1 link represented by 9x9 mtrx
719 FloatMatrix D1(9, 9);
720
721 double n [ 3 ];
722 // over all elements
723 for ( int t = 1; t <= noe; t++ ) {
724 // ??km?? TO DO: use list of interpolation elements instead of skipping...
725 if ( d->giveElement(t)->giveNumberOfDofManagers() > 2 ) {
726 continue; // skip interpolation elements
727 }
728
729 // TO DO: function "computeStiffnessMatrixOf1Link" can be used here
730 QCMaterialExtensionInterface *qcmei = static_cast< QCMaterialExtensionInterface * >( d->giveElement(t)->giveMaterial()->giveInterface(QCMaterialExtensionInterfaceType) );
731 if ( !qcmei ) {
732 OOFEM_ERROR("Material doesn't implement the required QC interface!");
733 }
734 double Etruss = qcmei->giveQcElasticParamneter();
735 double Ry = qcmei->giveQcPlasticParamneter();
736
737 double area = 0.;
738 SimpleCrossSection *cs = dynamic_cast< SimpleCrossSection * >( d->giveElement(t)->giveCrossSection() );
739 if ( cs ) {
740 area = cs->give(CS_Area, NULL);
741 } else {
742 OOFEM_ERROR( "Invalid CrossSection of link %d. simpleCS is only supported CS of links in QC simulation. \n", d->giveElement(t)->giveGlobalNumber() );
743 }
744
745 double x1 = d->giveElement(t)->giveDofManager(1)->giveCoordinate(1);
746 double y1 = d->giveElement(t)->giveDofManager(1)->giveCoordinate(2);
747 double z1 = d->giveElement(t)->giveDofManager(1)->giveCoordinate(3);
748 double x2 = d->giveElement(t)->giveDofManager(2)->giveCoordinate(1);
749 double y2 = d->giveElement(t)->giveDofManager(2)->giveCoordinate(2);
750 double z2 = d->giveElement(t)->giveDofManager(2)->giveCoordinate(3);
751 double TrussLength = sqrt( ( x2 - x1 ) * ( x2 - x1 ) + ( y2 - y1 ) * ( y2 - y1 ) + ( z2 - z1 ) * ( z2 - z1 ) );
752 n [ 0 ] = ( x2 - x1 ) / TrussLength;
753 n [ 1 ] = ( y2 - y1 ) / TrussLength;
754 n [ 2 ] = ( z2 - z1 ) / TrussLength;
755 // stiffness tensor
756 for ( int i = 1; i <= 3; i++ ) {
757 for ( int j = 1; j <= 3; j++ ) {
758 for ( int k = 1; k <= 3; k++ ) {
759 for ( int l = 1; l <= 3; l++ ) {
760 D1.at(3 * ( i - 1 ) + k, 3 * ( j - 1 ) + l) = TrussLength * Etruss * n [ i - 1 ] * n [ j - 1 ] * n [ k - 1 ] * n [ l - 1 ];
761 }
762 }
763 }
764 }
765
766 StiffnessTensor.add(D1); // add stfMtrX of 1 link to global stfMtrx
767
768 if ( !std :: isinf(Ry) ) {
769 S0 += TrussLength * area * Ry / 3;
770 }
771 } // for t=1:note
772
773 // divide by volume of element
774 StiffnessTensor.times(1 / volumeOfInterpolationMesh);
775 S0 = S0 / volumeOfInterpolationMesh;
776
777 transformStiffnessTensorToMatrix(D, StiffnessTensor);
778}
779
780
781bool
782Quasicontinuum :: stiffnessAssignment(std :: vector< FloatMatrix > &individualStiffnessTensors, FloatArray &individualS0, Domain *d, Element *e, qcNode *qn1, qcNode *qn2)
783{
784 FloatMatrix stfTensorOf1Link(9, 9);
785 double s0Of1Link;
786
787 // numbers of elements containing ending nodes
788 int end1 = qn1->giveMasterElementNumber();
789 int end2 = qn2->giveMasterElementNumber();
790
791 /*
792 * if ( (end1==0) && (end2==0) ) { // both ends are located outside
793 * // this case is solved explicitly before StiffnessAssignment
794 * } elseif ( (end1==0) || (end2==0) ) { // both ends are located outside
795 * // this case is solved explicitly before StiffnessAssignment
796 * }
797 */
798
799 if ( end1 == end2 ) { // both ends are in the same el.
800 // stiffness of link is assigned to this el.
801 computeStiffnessTensorOf1Link(stfTensorOf1Link, s0Of1Link, e, d);
802 int nel = end1; // number of interp element
803 int indx = interpolationElementIndices.at(nel); // number in list of interp elem
804 individualStiffnessTensors [ indx - 1 ].add(stfTensorOf1Link);
805 individualS0 [ indx - 1 ] += s0Of1Link;
806
807 return true;
808 } else { // ends are located in different elements -> all intersected el needs to be found
809 IntArray intersected; // to store numbers of intersected elem
810 std::vector<double> lengths_; // to store lengths ofintersections
811
812 computeIntersectionsOfLinkWithInterpElements(intersected, lengths_, d, e, qn1, qn2);
813 FloatArray lengths=FloatArray::fromVector(lengths_);
814
815 // check: is there any intersectted elements
816 int noIntersected = lengths.giveSize();
817 if ( noIntersected == 0 ) {
818 return false;
819 }
820
821 // check: is stiff. assigned to all parts of the link?
822 // TO DO: the same check is done in "computeIntersectionsOfLinkWith...".
823 // Use only return value here
824 double totalLength = distance(qn1->giveCoordinates(), qn2->giveCoordinates());
825 lengths.times(1 / totalLength); // it is better to use relative lengths
826 double sumLength = lengths.sum();
827 if ( (sumLength < 0.9999) || (sumLength > 1.0001) ) {
828 return false;
829 }
830
831 // if check OK ( sumLength == 1 )
832 computeStiffnessTensorOf1Link(stfTensorOf1Link, s0Of1Link, e, d);
833
834 for ( int i = 1; i <= noIntersected; i++ ) { // add stiff to all intersected elem
835 int nel = intersected [ i - 1 ]; // number of element
836 int indx = interpolationElementIndices.at(nel); // number in list of interp elem
837 individualStiffnessTensors [ indx - 1 ].add(lengths.at(i), stfTensorOf1Link);
838 individualS0 [ indx - 1 ] += lengths.at(i) * s0Of1Link;
839 }
840 return true;
841 } // ends are located in different elements
842
843 return false;
844}
845
846
847void
848Quasicontinuum :: computeIntersectionsOfLinkWithInterpElements(IntArray &intersected, std::vector<double> &lengths, Domain *d, Element *e, qcNode *qn1, qcNode *qn2)
849{
850 int dim = d->giveNumberOfSpatialDimensions();
851 if ( dim == 2 ) {
852 computeIntersectionsOfLinkWith2DTringleElements(intersected, lengths, d, e, qn1, qn2);
853 } else if ( dim == 3 ) {
854 computeIntersectionsOfLinkWith3DTetrahedraElements(intersected, lengths, d, e, qn1, qn2);
855 } else {
856 OOFEM_ERROR("unsupported number of dimensions");
857 }
858}
859
860
861bool
862Quasicontinuum :: computeIntersectionsOfLinkWith2DTringleElements(IntArray &intersected, std::vector<double> &lengths, Domain *d, Element *e, qcNode *qn1, qcNode *qn2)
863{
864 intersected.clear();
865 lengths.clear();
866
867 // numbers of elements containing ending nodes
868 int end1 = qn1->giveMasterElementNumber();
869 int end2 = qn2->giveMasterElementNumber();
870
871 if ( end2 < end1 ) { // swap?
872 std::swap(end1, end2);
873 std::swap(qn1, qn2);
874 }
875
876 // coordinates of ending nodes
877 const auto &X1 = qn1->giveCoordinates();
878 const auto &X2 = qn2->giveCoordinates();
879
880 double TotalLength = distance(X2, X1);
881
882 int numberOfIntersected = 0; // number of intersected elements
883
884 FloatArray vector(2);
885 std::vector<FloatArray> intersectCoords;
886 double iLen, sumLength = 0.0;
887
888 // ftiffness assignment for starting element (end1)
889 int iel = end1;
890 FloatArray iLens;
891
892 const auto &A = d->giveElement(iel)->giveNode(1)->giveCoordinates();
893 const auto &B = d->giveElement(iel)->giveNode(2)->giveCoordinates();
894 const auto &C = d->giveElement(iel)->giveNode(3)->giveCoordinates();
895 numberOfIntersected = intersectionTestSegmentTriangle2D(intersectCoords, A, B, C, X1, X2);
896
897 switch ( numberOfIntersected ) {
898 case 0: // no intersection with this element
899 lengths.push_back(0);
900 intersected.followedBy(iel); // cislo elementu
901 break;
902 case 1: // link starts in this element
903 iLen = distance(X1, intersectCoords[0]);
904 if ( iLen / TotalLength >= 1.e-6 ) { // intersection is not negligible
905 lengths.push_back(iLen);
906 intersected.followedBy(iel);
907 } else { // intersection is negligible
908 lengths.push_back(0);
909 intersected.followedBy(iel); // cislo elementu
910 }
911 break;
912 default: // 2 or more intersections
913
914 //lengths of all possible cobmination of intersection points
915 iLens.resize(numberOfIntersected);
916 for ( int nn = 1; nn <= numberOfIntersected; nn++ ) {
917 iLens.at(nn) = distance(X1, intersectCoords[nn - 1]);
918 }
919 iLen = iLens.at( iLens.giveIndexMaxElem() ); // real length is maximal one
920 if ( iLen / TotalLength >= 1.e-6 ) { // intersection is not negligible
921 lengths.push_back(iLen);
922 intersected.followedBy(iel);
923 } else { // intersection is negligible
924 lengths.push_back(0);
925 intersected.followedBy(iel); // cislo elementu
926 }
927 break;
928 }
929
930
931 // ftiffness assignment for the rest of the link
932 IntArray neighboursList, alreadyTestedElemList;
933 alreadyTestedElemList.clear();
934
935 int nome = interpolationElementNumbers.giveSize();
936
937 //bool secondEndReached = false;
938 int nextElement = end1;
939
940 for ( int ii = 1; ii <= nome; ii++ ) { // searching for nex intersected element
941 int nel = nextElement; // previous element number
942 nextElement = 0; // next element number (to be found)
943
944 // list of connected elements
945 neighboursList = connectivityTable [ interpolationElementIndices.at(nel) - 1 ];
946
947 // delete already intersected elements
948 for ( int k = 1; k <= intersected.giveSize(); k++ ) {
949 int index = neighboursList.findFirstIndexOf( intersected.at(k) );
950 if ( index != 0 ) {
951 neighboursList.erase(index);
952 }
953 }
954
955 // delete already tested elements
956 for ( int k = 1; k <= alreadyTestedElemList.giveSize(); k++ ) {
957 int index = neighboursList.findFirstIndexOf( alreadyTestedElemList.at(k) );
958 if ( index != 0 ) {
959 neighboursList.erase(index);
960 }
961 }
962
963
964 if ( neighboursList.giveSize() == 0 ) { // no elements to continue
965 //secondEndReached = false;
966 break; // ends searching for nex intersected element
967 }
968
969 for ( int k = 1; k <= neighboursList.giveSize(); k++ ) { // testing of neighbouring elements
970 iel = neighboursList.at(k);
971
972 const auto &A = d->giveElement(iel)->giveNode(1)->giveCoordinates();
973 const auto &B = d->giveElement(iel)->giveNode(2)->giveCoordinates();
974 const auto &C = d->giveElement(iel)->giveNode(3)->giveCoordinates();
975 numberOfIntersected = intersectionTestSegmentTriangle2D(intersectCoords, A, B, C, X1, X2);
976
977 bool breakFor = false; // go to next element?
978 switch ( numberOfIntersected ) {
979 case 0: // no intersection with (iel) element -> go to next element
980 alreadyTestedElemList.followedBy(iel);
981 continue;
982 case 1: // link ends here or there in only fake intersection
983 if ( iel == end2 ) { // end of the link in in this element
984 iLen = distance(X2, intersectCoords[0]);
985 if ( iLen / TotalLength >= 1.e-6 ) { // intersection is not negligible
986 lengths.push_back(iLen);
987 intersected.followedBy(iel);
988 // no break here, some elements still needs to be tested
989 } else { // intersection is negligible
990 lengths.push_back(0);
991 intersected.followedBy(iel); // cislo elementu
992 }
993 } else { // fake intersection (only touch with edge)
994 lengths.push_back(0);
995 intersected.followedBy(iel);
996 }
997 break;
998 default: // 2 or more intersections
999 if ( iel == end2 ) { // end of the link is inthis element
1000 //lengths of all possible cobmination of intersection points
1001 iLens.resize(numberOfIntersected);
1002 for ( int nn = 1; nn <= numberOfIntersected; nn++ ) {
1003 iLens.at(nn) = distance(X2, intersectCoords[nn - 1]);
1004 }
1005 iLen = iLens.at( iLens.giveIndexMaxElem() ); // real length is maximal
1006 if ( iLen / TotalLength >= 1.e-6 ) { // intersection is not negligible
1007 lengths.push_back(iLen);
1008 intersected.followedBy(iel);
1009 nextElement = iel;
1010 breakFor = true;
1011 break; // go to next element
1012 } else { // intersection is negligible
1013 lengths.push_back(0);
1014 intersected.followedBy(iel);
1015 }
1016 } else { // end of the link is NOT inthis elem
1017 iLens.resize(3); // combinations: 12 13 23
1018 iLens.zero();
1019 int m = 0;
1020 for ( int nn = 1; nn < numberOfIntersected; nn++ ) {
1021 for ( int ii = nn + 1; ii <= numberOfIntersected; ii++ ) {
1022 m += 1;
1023 iLens.at(m) = distance(intersectCoords[ii - 1], intersectCoords[nn - 1]);
1024 }
1025 }
1026 iLen = iLens.at( iLens.giveIndexMaxElem() ); // real length is maximum
1027 if ( iLen / TotalLength >= 1.e-6 ) { // intersection is not negligible
1028 lengths.push_back(iLen);
1029 intersected.followedBy(iel);
1030 nextElement = iel;
1031 breakFor = true;
1032 break; // go to next element
1033 } else { // intersection is negligible
1034 lengths.push_back(0);
1035 intersected.followedBy(iel);
1036 }
1037 } // end of the link is inthis element
1038 } // switch
1039
1040 if ( breakFor ) {
1041 break;
1042 } // go to next interpolation element
1043 } // over neigbouring elements
1044
1045
1046 // check: all length of link is assembles
1047 sumLength = std::accumulate(lengths.begin(), lengths.end(), 0.);
1048 if ( ( fabs(sumLength / TotalLength - 1) ) <= ( 0.0001 ) ) {
1049 return true;
1050 }
1051
1052 // check: there is no neighnouring element to continue
1053 if ( nextElement == 0 ) {
1054 return false;
1055 }
1056 } // searching for nex intersected element
1057
1058 return false;
1059}
1060
1061
1062bool
1063Quasicontinuum :: computeIntersectionsOfLinkWith3DTetrahedraElements(IntArray &intersected, std::vector<double> &lengths, Domain *d, Element *e, qcNode *qn1, qcNode *qn2)
1064{
1065 intersected.clear();
1066 lengths.clear();
1067
1068 // numbers of elements containing ending nodes
1069 int end1 = qn1->giveMasterElementNumber();
1070 int end2 = qn2->giveMasterElementNumber();
1071
1072 if ( end2 < end1 ) { // swap?
1073 std::swap(end1, end2);
1074 std::swap(qn1, qn2);
1075 }
1076
1077 // coordinates of ending nodes
1078 const auto &X1 = qn1->giveCoordinates();
1079 const auto &X2 = qn2->giveCoordinates();
1080
1081 double TotalLength = distance(X2, X1);
1082
1083 int numberOfIntersected = 0; // number of intersected elements
1084
1085 std::vector<FloatArray> intersectCoords;
1086 double iLen, sumLength = 0.0;
1087
1088 // ftiffness assignment for starting element (end1)
1089
1090 int iel = end1;
1091 FloatArray iLens;
1092
1093 const auto &A = d->giveElement(iel)->giveNode(1)->giveCoordinates();
1094 const auto &B = d->giveElement(iel)->giveNode(2)->giveCoordinates();
1095 const auto &C = d->giveElement(iel)->giveNode(3)->giveCoordinates();
1096 const auto &D = d->giveElement(iel)->giveNode(4)->giveCoordinates();
1097 numberOfIntersected = intersectionTestSegmentTetrahedra3D(intersectCoords, A, B, C, D, X1, X2);
1098
1099 switch ( numberOfIntersected ) {
1100 case 0: // no intersection with this element
1101 lengths.push_back(0);
1102 intersected.followedBy(iel); // cislo elementu
1103 break;
1104 case 1: // link starts in this element
1105 iLen = distance(X1, intersectCoords[0]);
1106 if ( iLen / TotalLength >= 1.e-6 ) { // intersection is not negligible
1107 lengths.push_back(iLen);
1108 intersected.followedBy(iel);
1109 } else { // intersection is negligible
1110 lengths.push_back(0);
1111 intersected.followedBy(iel);
1112 }
1113 break;
1114 default: // 2 or more intersections
1115
1116 //lengths of all possible cobmination of intersection points
1117 iLens.resize(numberOfIntersected);
1118 for ( int nn = 1; nn <= numberOfIntersected; nn++ ) {
1119 iLens.at(nn) = distance(X1, intersectCoords[nn - 1]);
1120 }
1121 iLen = iLens.at( iLens.giveIndexMaxElem() ); // real length is maximal one
1122 if ( iLen / TotalLength >= 1.e-6 ) { // intersection is not negligible
1123 lengths.push_back(iLen);
1124 intersected.followedBy(iel);
1125 } else { // intersection is negligible
1126 lengths.push_back(0);
1127 intersected.followedBy(iel);
1128 }
1129 break;
1130 }
1131
1132 // ftiffness assignment for the rest of the link
1133
1134 bool breakFor = false;
1135 IntArray neighboursList, alreadyTestedElemList;
1136 alreadyTestedElemList.clear();
1137
1138 int nome = interpolationElementNumbers.giveSize();
1139
1140 //bool secondEndReached = false;
1141 int nextElement = end1;
1142
1143 for ( int ii = 1; ii <= nome; ii++ ) { // searching for nex intersected element
1144 int nel = nextElement; // previous element number
1145 nextElement = 0; // next element number (to be found)
1146
1147 // list of connected elements
1148 neighboursList = connectivityTable [ interpolationElementIndices.at(nel) - 1 ];
1149
1150 // delete already intersected elements
1151 for ( int k = 1; k <= intersected.giveSize(); k++ ) {
1152 int index = neighboursList.findFirstIndexOf( intersected.at(k) );
1153 if ( index != 0 ) {
1154 neighboursList.erase(index);
1155 }
1156 }
1157
1158 // delete already tested elements
1159 for ( int k = 1; k <= alreadyTestedElemList.giveSize(); k++ ) {
1160 int index = neighboursList.findFirstIndexOf( alreadyTestedElemList.at(k) );
1161 if ( index != 0 ) {
1162 neighboursList.erase(index);
1163 }
1164 }
1165
1166 if ( neighboursList.giveSize() == 0 ) { // no elements to continue
1167 //secondEndReached = false;
1168 break; // ends searching for nex intersected element
1169 }
1170
1171 for ( int k = 1; k <= neighboursList.giveSize(); k++ ) { // testing of neighbouring elements
1172 int iel = neighboursList.at(k);
1173
1174 const auto &A = d->giveElement(iel)->giveNode(1)->giveCoordinates();
1175 const auto &B = d->giveElement(iel)->giveNode(2)->giveCoordinates();
1176 const auto &C = d->giveElement(iel)->giveNode(3)->giveCoordinates();
1177 const auto &D = d->giveElement(iel)->giveNode(4)->giveCoordinates();
1178 int numberOfIntersected = intersectionTestSegmentTetrahedra3D(intersectCoords, A, B, C, D, X1, X2);
1179
1180
1181 breakFor = false; // go to next interp elem
1182 switch ( numberOfIntersected ) {
1183 case 0: // no intersection with (iel) element -> go to next element
1184 alreadyTestedElemList.followedBy(iel);
1185 continue; // zadna tuhost se prvku neprirazuje
1186 case 1: // link ends here or there in only fake intersection
1187 if ( iel == end2 ) { // end of the link in in this element
1188 iLen = distance(X2, intersectCoords[0]);
1189 if ( iLen / TotalLength >= 1.e-6 ) { // intersection is not negligible
1190 lengths.push_back(iLen);
1191 intersected.followedBy(iel);
1192 // no break here, some elements still needs to be tested
1193 } else { // intersection is negligible
1194 lengths.push_back(0);
1195 intersected.followedBy(iel); // cislo elementu
1196 }
1197 } else { // fake intersection (only touch with edge)
1198 lengths.push_back(0);
1199 intersected.followedBy(iel);
1200 }
1201 break;
1202 default: // 2 or more intersections
1203 if ( iel == end2 ) { // end of the link is inthis element
1204 //lengths of all possible cobmination of intersection points
1205 iLens.resize(numberOfIntersected);
1206 for ( int nn = 1; nn <= numberOfIntersected; nn++ ) {
1207 iLens.at(nn) = distance(X2, intersectCoords[nn - 1]);
1208 }
1209 iLen = iLens.at( iLens.giveIndexMaxElem() ); // real length is maximal
1210 if ( iLen / TotalLength >= 1.e-6 ) { // intersection is not negligible
1211 lengths.push_back(iLen);
1212 intersected.followedBy(iel);
1213 nextElement = iel;
1214 breakFor = true;
1215 break; // go to next element
1216 } else { // intersection is negligible
1217 lengths.push_back(0);
1218 intersected.followedBy(iel);
1219 }
1220 } else { // end of the link is NOT inthis elem
1221 iLens.resize(6); // combinations: 12 13 14 23 24 34
1222 iLens.zero();
1223 int m = 0;
1224 for ( int nn = 1; nn <= numberOfIntersected; nn++ ) {
1225 for ( int ii = nn + 1; ii <= numberOfIntersected; ii++ ) {
1226 m += 1;
1227 iLens.at(m) = distance(intersectCoords[ii - 1], intersectCoords[nn - 1]);
1228 }
1229 }
1230 iLen = iLens.at( iLens.giveIndexMaxElem() ); // real length is maximum
1231 if ( iLen / TotalLength >= 1.e-6 ) { // intersection is not negligible
1232 lengths.push_back(iLen);
1233 intersected.followedBy(iel);
1234 nextElement = iel;
1235 breakFor = true;
1236 break; // go to next element
1237 } else { // intersection is negligible
1238 lengths.push_back(0);
1239 intersected.followedBy(iel);
1240 }
1241 } // end of the link is inthis element
1242 } // switch
1243
1244 if ( breakFor ) {
1245 break;
1246 } // go to next interp elem
1247 } // over neigbouring elements
1248
1249
1250 // check: all length of link is assembles
1251 sumLength = std::accumulate(lengths.begin(), lengths.end(), 0.);
1252 if ( ( fabs(sumLength / TotalLength - 1) ) <= ( 0.0001 ) ) {
1253 return true;
1254 }
1255
1256 // check: there is no neighnouring element to continue
1257 if ( nextElement == 0 ) {
1258 return false;
1259 }
1260 } // searching for nex intersected element
1261
1262 return false;
1263}
1264
1265
1266void
1267Quasicontinuum :: initializeConnectivityTableForInterpolationElements(Domain *d)
1268{
1269 // for each element save elements with shared node (edge, face,,,)
1270 int nome = interpolationElementNumbers.giveSize();
1271 int noVertices1, noVertices2;
1272 IntArray vertices1;
1273 connectivityTable.clear();
1274 connectivityTable.resize(nome);
1275
1276 for ( int j = 1; j <= nome; j++ ) { // all interpolation elements
1277 int elNum1 = interpolationElementNumbers.at(j);
1278 Element *e1 = d->giveElement(elNum1);
1279
1280 // vector of vertices numbers of el j
1281 noVertices1 = e1->giveNumberOfNodes();
1282 vertices1.resize(noVertices1);
1283 for ( int k = 1; k <= noVertices1; k++ ) { // fill in vector
1284 vertices1.at(k) = e1->giveNode(k)->giveNumber();
1285 }
1286 for ( int i = 1; i <= nome; i++ ) {
1287 if ( i == j ) {
1288 continue;
1289 } // is not itself neighbour
1290 // vector of vertices numbers of el j
1291 int elNum2 = interpolationElementNumbers.at(i);
1292 Element *e2 = d->giveElement(elNum2);
1293 noVertices2 = e2->giveNumberOfNodes();
1294 for ( int l = 1; l <= noVertices2; l++ ) { // fill in vector
1295 if ( vertices1.contains( e2->giveNode(l)->giveNumber() ) ) {
1296 connectivityTable [ j - 1 ].followedBy(elNum2); // add number of neighbour
1297 break;
1298 }
1299 }
1300 }
1301 }
1302}
1303
1304
1305bool
1306Quasicontinuum :: intersectionTestSegmentTrianglePlucker3D(FloatArray &intersectCoords, const FloatArray &A, const FloatArray &B, const FloatArray &C, const FloatArray &X1, const FloatArray &X2)
1307{
1308 // test if line (X2-X1) intersects tringle ABC (for 3D!)
1309 intersectCoords.clear();
1310
1311 // directional vektor
1312 double L = distance(X2, X1);
1313 double Ur1 = ( X2.at(1) - X1.at(1) ) / L;
1314 double Ur2 = ( X2.at(2) - X1.at(2) ) / L;
1315 double Ur3 = ( X2.at(3) - X1.at(3) ) / L;
1316 // cross product (needed for Plucker. coords)
1317 double Vr1 = Ur2 * X1.at(3) - Ur3 *X1.at(2);
1318 double Vr2 = Ur3 * X1.at(1) - Ur1 *X1.at(3);
1319 double Vr3 = Ur1 * X1.at(2) - Ur2 *X1.at(1);
1320 // Plucker. coords of line {U,UxX1}
1321 // Pr = [Ur, Vr];
1322
1323 // vectors of edges: (order is important!)
1324 FloatArray U1(3), U2(3), U3(3);
1325 for ( int i = 1; i <= 3; i++ ) {
1326 U1.at(i) = B.at(i) - A.at(i);
1327 U2.at(i) = C.at(i) - B.at(i);
1328 U3.at(i) = A.at(i) - C.at(i);
1329 }
1330
1331 // cross product (needed for Plucker. coords)
1332 FloatArray V1(3), V2(3), V3(3);
1333 // cross(U1,A);
1334 V1.at(1) = U1.at(2) * A.at(3) - U1.at(3) * A.at(2);
1335 V1.at(2) = U1.at(3) * A.at(1) - U1.at(1) * A.at(3);
1336 V1.at(3) = U1.at(1) * A.at(2) - U1.at(2) * A.at(1);
1337 // cross(U2,B);
1338 V2.at(1) = U2.at(2) * B.at(3) - U2.at(3) * B.at(2);
1339 V2.at(2) = U2.at(3) * B.at(1) - U2.at(1) * B.at(3);
1340 V2.at(3) = U2.at(1) * B.at(2) - U2.at(2) * B.at(1);
1341 // cross(U3,C);
1342 V3.at(1) = U3.at(2) * C.at(3) - U3.at(3) * C.at(2);
1343 V3.at(2) = U3.at(3) * C.at(1) - U3.at(1) * C.at(3);
1344 V3.at(3) = U3.at(1) * C.at(2) - U3.at(2) * C.at(1);
1345
1346
1347 // permuted inner products Pr(.)P1 = Ur.V1 + U1.Vr
1348 double S1 = Ur1 * V1.at(1) + Ur2 *V1.at(2) + Ur3 *V1.at(3) + U1.at(1) * Vr1 + U1.at(2) * Vr2 + U1.at(3) * Vr3; // dot(Ur,V1) + dot(U1,Vr);
1349 double S2 = Ur1 * V2.at(1) + Ur2 *V2.at(2) + Ur3 *V2.at(3) + U2.at(1) * Vr1 + U2.at(2) * Vr2 + U2.at(3) * Vr3; // dot(Ur,V2) + dot(U2,Vr);
1350 double S3 = Ur1 * V3.at(1) + Ur2 *V3.at(2) + Ur3 *V3.at(3) + U3.at(1) * Vr1 + U3.at(2) * Vr2 + U3.at(3) * Vr3; // dot(Ur,V3) + dot(U3,Vr);
1351
1352 // tolerance ??
1353 double TOL = 1e-11;
1354 if ( fabs(S1) <= TOL ) {
1355 S1 = 0;
1356 }
1357 if ( fabs(S2) <= TOL ) {
1358 S2 = 0;
1359 }
1360 if ( fabs(S3) <= TOL ) {
1361 S3 = 0;
1362 }
1363
1364 // in planar test
1365 if ( ( S1 == 0 ) && ( S2 == 0 ) && ( S3 == 0 ) ) {
1366 // segment is in the same plane as triangle
1367 // in this case it means no ontersection
1368 // for tetrahedra elements there will be another 2 intersections with remaining faces
1369 intersectCoords.clear();
1370 return false; // no intersection
1371 }
1372
1373
1374 // same orientation -> intersection with line (not necessarily with segment)
1375 if ( ( ( S1 >= 0 ) && ( S2 >= 0 ) && ( S3 >= 0 ) ) || ( ( S1 <= 0 ) && ( S2 <= 0 ) && ( S3 <= 0 ) ) ) {
1376 // calculation of intersection coords
1377 double S = S1 + S2 + S3;
1378 // from barycentric coords
1379 double u1 = S1 / S;
1380 double u2 = S2 / S;
1381 double u3 = S3 / S;
1382 // to cartesian
1383 // Px = [x y z] = u1*C + u2*A +u3*B; // multiple by opposite vertex
1384 double x = u1 * C.at(1) + u2 *A.at(1) + u3 *B.at(1);
1385 double y = u1 * C.at(2) + u2 *A.at(2) + u3 *B.at(2);
1386 double z = u1 * C.at(3) + u2 *A.at(3) + u3 *B.at(3);
1387
1388 // is interection on line segment
1389
1390 // intersection parameter
1391 double t;
1392 // Pk = [x y z] = X1 + t*(X2-X1)
1393 if ( ( X2.at(1) - X1.at(1) ) != 0 ) { // x-coord will be used
1394 t = ( x - X1.at(1) ) / ( X2.at(1) - X1.at(1) ); // parameter on segment
1395 } else {
1396 if ( ( X2.at(2) - X1.at(2) ) != 0 ) { // y-coord will be used
1397 t = ( y - X1.at(2) ) / ( X2.at(2) - X1.at(2) ); // parameter on segment
1398 } else { // z-coord will be used
1399 t = ( z - X1.at(3) ) / ( X2.at(3) - X1.at(3) ); // parameter on segment
1400 }
1401 }
1402
1403 // is interection on line segment? (0<t<1)
1404 double EPS = 1.0e-12; // numerical tolerance
1405 if ( ( 0 < t + EPS ) && ( t - EPS < 1 ) ) {
1406 intersectCoords.resize(3);
1407 intersectCoords.at(1) = x;
1408 intersectCoords.at(2) = y;
1409 intersectCoords.at(3) = z;
1410 return true;
1411 } else {
1412 intersectCoords.clear();
1413 return false; // no intersection
1414 }
1415 } else { //different orientation -> no intersection
1416 intersectCoords.clear();
1417 return false; // no intersection
1418 } // if same orientation
1419}
1420
1421
1422int
1423Quasicontinuum :: intersectionTestSegmentTetrahedra3D(std::vector<FloatArray> &intersectCoords,
1424 const FloatArray &A, const FloatArray &B, const FloatArray &C, const FloatArray &D, const FloatArray &X1, const FloatArray &X2)
1425{
1426 // test if line (X2-X1) intersects tetrahedra ABCD (for 3D!)
1427 intersectCoords.clear();
1428 FloatArray intersectCoord;
1429
1430 // face 1
1431 if ( intersectionTestSegmentTrianglePlucker3D(intersectCoord, A, B, C, X1, X2) ) {
1432 intersectCoords.push_back(intersectCoord);
1433 }
1434
1435 // face 2
1436 if ( intersectionTestSegmentTrianglePlucker3D(intersectCoord, A, D, B, X1, X2) ) {
1437 intersectCoords.push_back(intersectCoord);
1438 }
1439
1440 // face 3
1441 if ( intersectionTestSegmentTrianglePlucker3D(intersectCoord, B, D, C, X1, X2) ) {
1442 intersectCoords.push_back(intersectCoord);
1443 }
1444
1445 // face 4
1446 if ( intersectionTestSegmentTrianglePlucker3D(intersectCoord, A, C, D, X1, X2) ) {
1447 intersectCoords.push_back(intersectCoord);
1448 }
1449
1450 return (int)intersectCoords.size();
1451}
1452
1453
1454int
1455Quasicontinuum :: intersectionTestSegmentTriangle2D(std::vector<FloatArray> &intersectCoords,
1456 const FloatArray &A, const FloatArray &B, const FloatArray &C, const FloatArray &U1, const FloatArray &U2)
1457{
1458 // test if line (X2-X1) intersects tringle ABC (for 2D!)
1459 intersectCoords.clear();
1460 FloatArray intersectCoord;
1461
1462 // edge 1
1463 if ( intersectionTestSegmentSegment2D(intersectCoord, A, B, U1, U2) ) {
1464 intersectCoords.push_back(intersectCoord);
1465 }
1466
1467 // edge 2
1468 if ( intersectionTestSegmentSegment2D(intersectCoord, B, C, U1, U2) ) {
1469 intersectCoords.push_back(intersectCoord);
1470 }
1471
1472 // edge 3
1473 if ( intersectionTestSegmentSegment2D(intersectCoord, A, C, U1, U2) ) {
1474 intersectCoords.push_back(intersectCoord);
1475 }
1476
1477 return (int)intersectCoords.size();
1478}
1479
1480
1481bool
1482Quasicontinuum :: intersectionTestSegmentSegment2D(FloatArray &intersectCoords, const FloatArray &A1, const FloatArray &A2, const FloatArray &B1, const FloatArray &B2)
1483{
1484 //intersectionTest of 2 segments A1-A2 B1-B2 (2D only)
1485
1486 double a1x = A1.at(1);
1487 double a1y = A1.at(2);
1488 double a2x = A2.at(1);
1489 double a2y = A2.at(2);
1490 double b1x = B1.at(1);
1491 double b1y = B1.at(2);
1492 double b2x = B2.at(1);
1493 double b2y = B2.at(2);
1494
1495 // y=f*x+g
1496 double f1 = std :: numeric_limits< float > :: infinity();
1497 double f2 = std :: numeric_limits< float > :: infinity();
1498 if ( a1x != a2x ) {
1499 f1 = -( a2y - a1y ) / ( a1x - a2x );
1500 }
1501 if ( b1x != b2x ) {
1502 f2 = -( b2y - b1y ) / ( b1x - b2x );
1503 }
1504
1505 double g1 = a1y - f1 * a1x;
1506 double g2 = b1y - f2 * b1x;
1507
1508 // % parallels
1509 if ( f1 == f2 ) {
1510 intersectCoords.clear();
1511 return false;
1512 }
1513
1514 // intersection...
1515 double x, y;
1516 if ( a1x == a2x ) {
1517 x = a1x;
1518 y = f2 * a1x + g2;
1519 } else if ( b1x == b2x ) {
1520 x = b1x;
1521 y = f1 * b1x + g1;
1522 } else {
1523 x = ( g2 - g1 ) / ( f1 - f2 );
1524 y = f1 * x + g1;
1525 }
1526
1527 // is intersection on both segments? (it is not enough to test x-coords only)
1528 double x1, x2, x3, x4;
1529 if ( a1x <= a2x ) {
1530 x1 = a1x;
1531 x2 = a2x;
1532 } else {
1533 x1 = a2x;
1534 x2 = a1x;
1535 }
1536 if ( b1x <= b2x ) {
1537 x3 = b1x;
1538 x4 = b2x;
1539 } else {
1540 x3 = b2x;
1541 x4 = b1x;
1542 }
1543 double y1, y2, y3, y4;
1544 if ( a1y <= a2y ) {
1545 y1 = a1y;
1546 y2 = a2y;
1547 } else {
1548 y1 = a2y;
1549 y2 = a1y;
1550 }
1551 if ( b1y <= b2y ) {
1552 y3 = b1y;
1553 y4 = b2y;
1554 } else {
1555 y3 = b2y;
1556 y4 = b1y;
1557 }
1558
1559 // test
1560 double EPS = 1e-10;
1561 if ( ( x1 <= x + EPS ) && ( x <= x2 + EPS ) && ( x3 <= x + EPS ) && ( x <= x4 + EPS ) && ( y1 <= y + EPS ) && ( y <= y2 + EPS ) && ( y3 <= y + EPS ) && ( y <= y4 + EPS ) ) {
1562 intersectCoords = Vec2(x, y);
1563 return true;
1564 } else {
1565 intersectCoords.clear();
1566 return false;
1567 }
1568}
1569
1570
1571void
1572Quasicontinuum :: transformStiffnessTensorToMatrix(FloatMatrix &matrix, const FloatMatrix &tensor)
1573{
1574 // transform stiff. tensor 9x9 to stiff. matrix 6x6 (universal for 3D and 2D)
1575 IntArray indicesI = {1, 2, 3, 2, 1, 1};
1576 IntArray indicesJ = {1, 2, 3, 3, 3, 2};
1577 IntArray indicesK = {1, 2, 3, 2, 1, 1};
1578 IntArray indicesL = {1, 2, 3, 3, 3, 2};
1579
1580 for ( int ii = 1; ii <= 6; ii++ ) {
1581 for ( int jj = 1; jj <= 6; jj++ ) {
1582 int i = indicesI.at(ii);
1583 int j = indicesJ.at(ii);
1584
1585 int k = indicesK.at(jj);
1586 int l = indicesL.at(jj);
1587
1588 matrix.at(ii, jj) = tensor.at(3 * ( i - 1 ) + k, 3 * ( j - 1 ) + l);
1589 }
1590 }
1591}
1592} // end namespace oofem
#define _IFT_AnisotropicLinearElasticMaterial_stiff
Stiffness coefficients arranged by rows from the diagonal to the right (21 values).
virtual double give(CrossSectionProperty a, GaussPoint *gp) const
double giveCoordinate(int i) const
Definition dofmanager.h:383
const FloatArray & giveCoordinates() const
Definition dofmanager.h:390
void resizeElements(int _newSize)
Resizes the internal data structure to accommodate space for _newSize elements.
Definition domain.C:446
void setElement(int i, std::unique_ptr< Element > obj)
Sets i-th component. The component will be further managed and maintained by domain object.
Definition domain.C:467
int giveNumberOfMaterialModels() const
Returns number of material models in domain.
Definition domain.h:465
void resizeMaterials(int _newSize)
Resizes the internal data structure to accommodate space for _newSize materials.
Definition domain.C:448
const IntArray & giveElementsWithMaterialNum(int iMaterialNum) const
Definition domain.C:214
int giveNumberOfElements() const
Returns number of elements in domain.
Definition domain.h:463
int giveNumberOfDofManagers() const
Returns number of dof managers in domain.
Definition domain.h:461
Element * giveElement(int n)
Definition domain.C:165
int giveNumberOfSpatialDimensions()
Returns number of spatial dimensions.
Definition domain.C:1137
EngngModel * giveEngngModel()
Definition domain.C:419
void resizeCrossSectionModels(int _newSize)
Resizes the internal data structure to accommodate space for _newSize cross section models.
Definition domain.C:447
void setMaterial(int i, std::unique_ptr< Material > obj)
Sets i-th component. The component will be further managed and maintained by domain object.
Definition domain.C:469
int giveNumberOfCrossSectionModels() const
Returns number of cross section models in domain.
Definition domain.h:467
void setCrossSection(int i, std::unique_ptr< CrossSection > obj)
Sets i-th component. The component will be further managed and maintained by domain object.
Definition domain.C:468
void setField(int item, InputFieldType id)
void setMaterial(int matIndx)
Definition element.h:686
int giveGlobalNumber() const
Definition element.h:1129
Node * giveNode(int i) const
Definition element.h:629
static ParamKey IPK_Element_nodes
Definition element.h:200
virtual int giveNumberOfNodes() const
Definition element.h:703
const IntArray & giveDofManArray() const
Definition element.h:611
virtual void setCrossSection(int csIndx)
Definition element.h:692
virtual double computeVolumeAreaOrLength()
Computes the volume, area or length of the element depending on its spatial dimension.
Definition element.C:1081
virtual Material * giveMaterial()
Definition element.C:523
virtual int giveNumberOfDofManagers() const
Definition element.h:695
DofManager * giveDofManager(int i) const
Definition element.C:553
CrossSection * giveCrossSection()
Definition element.C:534
int giveNumber() const
Definition femcmpnn.h:104
Index size() const
Definition floatarray.h:162
void resize(Index s)
Definition floatarray.C:94
double & at(Index i)
Definition floatarray.h:202
Index giveSize() const
Returns the size of receiver.
Definition floatarray.h:261
double sum() const
Definition floatarray.C:874
static FloatArray fromVector(const std::vector< double > &v)
Definition floatarray.C:131
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
int giveIndexMaxElem(void)
Definition floatarray.C:508
void times(double s)
Definition floatarray.C:834
void times(double f)
void add(const FloatMatrix &a)
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
void followedBy(const IntArray &b, int allocChunk=0)
Definition intarray.C:94
void resize(int n)
Definition intarray.C:73
bool contains(int value) const
Definition intarray.h:292
void erase(int pos)
Definition intarray.C:112
int findFirstIndexOf(int value) const
Definition intarray.C:280
int & at(std::size_t i)
Definition intarray.h:104
int giveSize() const
Definition intarray.h:211
virtual int giveQcNodeType()
Definition node.h:177
virtual double giveQcElasticParamneter()=0
virtual double giveQcPlasticParamneter()=0
void setActivatedElementList(IntArray elemList)
void setActivatedNodeList(IntArray nodeList, Domain *d)
void createGlobalStiffnesMatrix(FloatMatrix &Diso, double &S0, Domain *d, int homMtrxType, double volumeOfInterpolationMesh)
IntArray interpolationElementNumbers
bool intersectionTestSegmentTrianglePlucker3D(FloatArray &intersectCoords, const FloatArray &A, const FloatArray &B, const FloatArray &C, const FloatArray &X1, const FloatArray &X2)
bool stiffnessAssignment(std::vector< FloatMatrix > &individualStiffnessTensors, FloatArray &individialS0, Domain *d, Element *e, qcNode *qn1, qcNode *qn2)
bool intersectionTestSegmentSegment2D(FloatArray &intersectCoords, const FloatArray &A1, const FloatArray &A2, const FloatArray &B1, const FloatArray &B2)
bool computeIntersectionsOfLinkWith3DTetrahedraElements(IntArray &intersected, std::vector< double > &lengths, Domain *d, Element *e, qcNode *qn1, qcNode *qn2)
bool computeIntersectionsOfLinkWith2DTringleElements(IntArray &intersected, std::vector< double > &lengths, Domain *d, Element *e, qcNode *qn1, qcNode *qn2)
std::vector< IntArray > connectivityTable
void homogenizationOfStiffMatrix(double &homogenizedE, double &homogenizedNu, const FloatMatrix &Diso)
void computeStiffnessTensorOf1Link(FloatMatrix &D1, double &S0, Element *e, Domain *d)
IntArray interpolationElementIndices
void transformStiffnessTensorToMatrix(FloatMatrix &matrix, const FloatMatrix &tensor)
int intersectionTestSegmentTetrahedra3D(std::vector< FloatArray > &intersectCoords, const FloatArray &A, const FloatArray &B, const FloatArray &C, const FloatArray &D, const FloatArray &X1, const FloatArray &X2)
void initializeConnectivityTableForInterpolationElements(Domain *d)
void computeIntersectionsOfLinkWithInterpElements(IntArray &intersected, std::vector< double > &lengths, Domain *d, Element *e, qcNode *qn1, qcNode *qn2)
std::vector< IntArray > interpolationMeshNodes
int intersectionTestSegmentTriangle2D(std::vector< FloatArray > &intersectCoords, const FloatArray &A, const FloatArray &B, const FloatArray &C, const FloatArray &U1, const FloatArray &U2)
double give(int aProperty, GaussPoint *gp) const override
virtual int giveMasterElementNumber()
Definition qcnode.h:103
#define OOFEM_WARNING(...)
Definition error.h:80
#define OOFEM_ERROR(...)
Definition error.h:79
#define _IFT_IsotropicLinearElasticMaterial_talpha
#define _IFT_IsotropicLinearElasticMaterial_n
#define _IFT_IsotropicLinearElasticMaterial_e
#define TOL
#define _IFT_Material_density
Definition material.h:52
#define S(p)
Definition mdm.C:469
static FloatArray Vec2(const double &a, const double &b)
Definition floatarray.h:606
@ CS_Area
Area.
@ CS_Thickness
Thickness.
static FloatArray VecX(std::initializer_list< double > ini)
Definition floatarray.h:614
ClassFactory & classFactory
@ QCMaterialExtensionInterfaceType
double distance(const FloatArray &x, const FloatArray &y)
#define _IFT_SimpleCrossSection_thick
#define _IFT_SimpleCrossSection_width

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