TexGen
SimulationAbaqus.cpp
Go to the documentation of this file.
1/*=============================================================================
2TexGen: Geometric textile modeller.
3Copyright (C) 2006 Martin Sherburn
4
5This program is free software; you can redistribute it and/or
6modify it under the terms of the GNU General Public License
7as published by the Free Software Foundation; either version 2
8of the License, or (at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18=============================================================================*/
19
20#include "PrecompiledHeaders.h"
21#include "SimulationAbaqus.h"
23#include "TexGen.h"
24#include "Materials.h"
25
26#define FIRST_HALF 0
27#define SECOND_HALF 1
28
29using namespace TexGen;
30
31CSimulationAbaqus::CSimulationAbaqus(void)
32: m_iTotalNumNodes(0)
33, m_bIncludePlates(false)
34, m_dInitialPlateGap(0)
35, m_bWholeSurfaces(false)
36{
37}
38
40{
41}
42
43bool CSimulationAbaqus::CreateAbaqusInputFile(CTextile &Textile, string Filename, bool bRegenerateMesh, int iElementType, bool bAdjustMesh, double Tolerance )
44{
45 //PROFILE_BEGIN(Begin)
46 AddExtensionIfMissing(Filename, ".inp");
47 TGLOG("Replacing spaces in filename with underscore for ABAQUS compatibility");
48 Filename = ReplaceFilenameSpaces( Filename );
49
50 int iNumYarns = Textile.GetNumYarns();
51 if (iNumYarns == 0)
52 return false;
53 const CDomain* pDomain = Textile.GetDomain();
54 if (!pDomain)
55 {
56 TGERROR("Unable to create ABAQUS input file: No domain specified");
57 return false;
58 }
59
60 Textile.AddVolumeToMesh(m_YarnMeshes, true);
61 if (m_YarnMeshes.size() != iNumYarns)
62 {
63 TGERROR("Unable to create ABAQUS input file: Failed to create volume mesh for yarns ");
64 return false;
65 }
66
67 const vector<XYZ> &Repeats = Textile.GetYarn(0)->GetRepeats();
68 map<string, vector<ELEMENT_FACE> > SurfaceDefinitions;
69
70 if ( !bRegenerateMesh ) // This is time consuming - if regenerating will get surfaces later
71 {
72 //PROFILE_BLOCK(GetYarnSurfaces)
73 CreateSurfaceDefinitions( iNumYarns, Repeats, SurfaceDefinitions);
74 }
75
76 vector<POINT_INFO> YarnElementInfo;
77 vector< vector<POINT_INFO> > YarnElementTypesInfo;
78
79 if ( bAdjustMesh )
80 {
81 CAdjustMeshInterference AdjustMesh;
82
83 TGLOG("Adjusting mesh");
84 if ( !AdjustMesh.AdjustMesh( Textile, m_YarnMeshes, Tolerance ) )
85 {
86 return false;
87 }
88
89 if ( bRegenerateMesh )
90 {
91 TGLOG("Regenerating mesh using adjusted points");
92 AdjustMesh.AdjustSectionMeshes( Textile, m_YarnMeshes );
93
94 Textile.AddVolumeToMesh(m_YarnMeshes, true);
95 if (m_YarnMeshes.size() != iNumYarns)
96 {
97 TGERROR("Unable to create ABAQUS input file: Failed to create volume mesh for yarns ");
98 return false;
99 }
100
101 SurfaceDefinitions.clear();
102 CreateSurfaceDefinitions( iNumYarns, Repeats, SurfaceDefinitions);
103 }
104 }
105
106 //BuildIndexOffsets();
108 int i;
109 vector<POINT_INFO> ElementsInfo;
110 TGLOG("Getting point information");
111 {
112 // PROFILE_BLOCK(GetPointInformation)
113 for ( i = 0; i < iNumYarns; ++i )
114 {
115 for (int j = 0; j < CMesh::NUM_ELEMENT_TYPES; ++j )
116 {
117 if ( j == CMesh::POLYGON )
118 continue;
119 YarnElementInfo.clear();
120 Textile.GetPointInformation( m_YarnMeshes[i].GetElementCenters( (CMesh::ELEMENT_TYPE)j ), YarnElementInfo, i, 0.005 );
121 if ( i == 0 ) // If first yarn add vector for each element type
122 YarnElementTypesInfo.push_back( YarnElementInfo );
123 else // Subsequent yarns add to end of appropriate element vector
124 {
125
126 YarnElementTypesInfo[j].insert( YarnElementTypesInfo[j].end(), YarnElementInfo.begin(), YarnElementInfo.end() );
127 }
128 }
129 }
130 vector< vector<POINT_INFO> >::iterator itYarnElementTypesInfo;
131 for ( itYarnElementTypesInfo = YarnElementTypesInfo.begin(); itYarnElementTypesInfo != YarnElementTypesInfo.end(); ++itYarnElementTypesInfo )
132 {
133 ElementsInfo.insert( ElementsInfo.end(), itYarnElementTypesInfo->begin(), itYarnElementTypesInfo->end() );
134 }
135 }
136 vector<SECTION_VF_DATA> VolFractionData;
137
138 for(i=0; i<iNumYarns; ++i) // Add meshes into single mesh
139 {
140 if ( !m_YarnMeshes[i].NodesEmpty() )
141 {
142 if ( bAdjustMesh && !bRegenerateMesh ) // Can just use volume fractions straight from textile if have regenerated mesh
143 {
144 TGLOG("Recalculating volume fractions for adjusted mesh");
145 GetSectionVolumeFractions( Textile, VolFractionData, i );
146
147 }
148 m_YarnMeshes[i].RemoveElementType(CMesh::POLYGON); // Don't need POLYGON sections any more & dont want to copy into global mesh
149 m_YarnMeshes[i].RemoveUnreferencedNodes();
151 }
152#ifdef _DEBUG
153 m_YarnMeshes[i].SaveToVTK( "c:\\Program Files\\TexGen\\AdjustedMesh" + stringify(i) );
154#endif
155 }
156
157 // then assemble
158
160
161 if ( bAdjustMesh && !bRegenerateMesh)
162 {
163 vector<SECTION_VF_DATA> MidVFData;
164 CreateMidPointVolumeFractions( VolFractionData, MidVFData );
165 GetElementVolumeFractions( ElementsInfo, MidVFData );
166 }
167
168 TGLOG("Saving to ABAQUS");
169 m_TextileMesh.SaveToABAQUS(Filename, &ElementsInfo, false, false, iElementType);
171
172 ofstream Output(Filename.c_str(), ios::app);
173
174 m_Materials.SetupMaterials( Textile );
175 TGLOG("Creating materials");
176 CreateMaterials(Output, Filename);
177 TGLOG("Creating surfaces");
178 CreateSurfaces(Output, SurfaceDefinitions);
180 {
181 TGLOG("Creating compression plates");
183 }
184
185 vector<int> YarnCenterNodes;
186 int iNodeIndex;
187 for (i=0; i<iNumYarns; ++i)
188 {
189 if ( !m_YarnMeshes[i].NodesEmpty() )
190 {
191 iNodeIndex = GetGlobalNodeIndex(i, GetCenterNode(m_YarnMeshes[i]));
192 YarnCenterNodes.push_back(iNodeIndex);
193 }
194 }
195
196 TGLOG("Creating periodic boundaries");
197 CreatePeriodicBoundaries(Output, *pDomain);
198 vector<CLinearTransformation>::iterator itDeformation;
199
200
201 TGLOG("Creating step");
202 CreateStep(Output);
203
204 TGLOG("Creating contacts");
205 CreateContacts(Output, Textile);
206 for (itDeformation = m_DeformationSteps.begin(); itDeformation != m_DeformationSteps.end(); ++itDeformation)
207 {
208 CreateBoundary(Output, *itDeformation, YarnCenterNodes, Repeats);
209 }
210 TGLOG("Completed ABAQUS input file");
211 //PROFILE_END();
212 //PROFILER_UPDATE();
213 //PROFILER_OUTPUT("ProfileDryFibreExportOutput.txt");
214 return true;
215}
216
217void CSimulationAbaqus::CreateSurfaceDefinitions( int iNumYarns, const vector<XYZ> &Repeats, map<string, vector<ELEMENT_FACE> > &SurfaceDefinitions)
218{
219 for (int i=0; i<iNumYarns; ++i)
220 {
221 TGLOG("Creating yarn " << i << " surface definitions");
222 if ( m_bWholeSurfaces )
223 {
224 vector<ELEMENT_FACE> Faces;
225 GetYarnSurface( i, Repeats, Faces );
226 SurfaceDefinitions["YarnSurf" + stringify(i)] = Faces;
227 }
228 else
229 {
230 vector<ELEMENT_FACE> UpperFaces, LowerFaces;
231 GetYarnSurfaces( i, Repeats, UpperFaces, LowerFaces );
232 SurfaceDefinitions["Yarn" + stringify(i) + "Lower"] = LowerFaces;
233 SurfaceDefinitions["Yarn" + stringify(i) + "Upper"] = UpperFaces;
234 }
235 }
236}
237
238void CSimulationAbaqus::GetYarnSurfaces(int iYarn, const vector<XYZ> &Repeats, vector<ELEMENT_FACE> &UpperFaces, vector<ELEMENT_FACE> &LowerFaces )
239{
240 CMesh &VolumeMesh = m_YarnMeshes[iYarn];
241
242 CMesh SurfaceMesh = VolumeMesh;
244 SurfaceMesh.RemoveUnreferencedNodes();
245 SurfaceMesh.ConvertToSurfaceMesh();
246
247 // Make a list of nodes which lie on the yarn's end
248 set<int> BoundaryNodes;
249 vector<XYZ>::const_iterator itRepeat;
250 for (itRepeat=Repeats.begin(); itRepeat!=Repeats.end(); ++itRepeat)
251 {
252 vector<pair<int, int> > NodePairs;
253 SurfaceMesh.GetNodePairs(*itRepeat, NodePairs);
254 vector<pair<int, int> >::iterator itNodePair;
255 for (itNodePair = NodePairs.begin(); itNodePair != NodePairs.end(); ++itNodePair)
256 {
257 BoundaryNodes.insert(itNodePair->first);
258 BoundaryNodes.insert(itNodePair->second);
259 }
260 }
261
262 // Get the yarn surface
263 int i, iType, iBoundaryNodes;
264 list<int>::iterator itIndex;
265
266 ELEMENT_FACE Face;
267 for (iType = 0; iType < CMesh::NUM_ELEMENT_TYPES; ++iType)
268 {
270 if ( Type != CMesh::POLYGON )
271 {
272 list<int> &Indices = SurfaceMesh.GetIndices(Type);
273 for (itIndex = Indices.begin(); itIndex != Indices.end(); )
274 {
275 vector<int> ElemIndices;
276 iBoundaryNodes = 0;
277 for (i=0; i<CMesh::GetNumNodes(Type); ++i)
278 {
279 iBoundaryNodes += (int)BoundaryNodes.count(*itIndex);
280 ElemIndices.push_back(*itIndex);
281 ++itIndex;
282 }
283 // Filter out any faces which lie on the yarn boundary
284 if (iBoundaryNodes != (int)ElemIndices.size())
285 {
286 XYZ N1 = SurfaceMesh.GetNode(ElemIndices[0]);
287 XYZ N2 = SurfaceMesh.GetNode(ElemIndices[1]);
288 XYZ N3 = SurfaceMesh.GetNode(ElemIndices[2]);
289 XYZ Normal = CrossProduct(N2-N1, N3-N1);
290 // Let's filter out all the faces based on their normal
291 Face = FindFaceIndex(iYarn, ElemIndices);
292 if ( Normal.z > 0 ) // Upper surface
293 {
294 UpperFaces.push_back(Face);
295 }
296 else // Lower surface
297 {
298 LowerFaces.push_back(Face);
299 }
300 }
301 }
302 }
303 }
304}
305
306void CSimulationAbaqus::GetYarnSurface(int iYarn, const vector<XYZ> &Repeats, vector<ELEMENT_FACE> &Faces )
307{
308 // This function assumes that the yarn is repeating. If no repeats are specified, or the domain does not
309 // match a whole number of repeats then no surface will be saved
310 CMesh &VolumeMesh = m_YarnMeshes[iYarn];
311
312 CMesh SurfaceMesh = VolumeMesh;
314 SurfaceMesh.RemoveUnreferencedNodes();
315 //SurfaceMesh.SaveToVTK("C://Users//epzlpb//TexGen//Knit//VolumeMesh");
316 SurfaceMesh.ConvertToSurfaceMesh();
317 //SurfaceMesh.SaveToVTK("C://Users//epzlpb//TexGen//Knit//SurfaceMesh");
318
319 // Make a list of nodes which lie on the yarn's end
320 set<int> BoundaryNodes;
321 vector<XYZ>::const_iterator itRepeat;
322 for (itRepeat=Repeats.begin(); itRepeat!=Repeats.end(); ++itRepeat)
323 {
324 vector<pair<int, int> > NodePairs;
325 SurfaceMesh.GetNodePairs(*itRepeat, NodePairs);
326 vector<pair<int, int> >::iterator itNodePair;
327 for (itNodePair = NodePairs.begin(); itNodePair != NodePairs.end(); ++itNodePair)
328 {
329 BoundaryNodes.insert(itNodePair->first);
330 BoundaryNodes.insert(itNodePair->second);
331 }
332 }
333
334 // Get the yarn surface
335 int i, iType, iBoundaryNodes;
336 list<int>::iterator itIndex;
337
338 ELEMENT_FACE Face;
339 for (iType = 0; iType < CMesh::NUM_ELEMENT_TYPES; ++iType)
340 {
342 if ( Type != CMesh::POLYGON )
343 {
344 list<int> &Indices = SurfaceMesh.GetIndices(Type);
345 for (itIndex = Indices.begin(); itIndex != Indices.end(); )
346 {
347 vector<int> ElemIndices;
348 iBoundaryNodes = 0;
349 for (i=0; i<CMesh::GetNumNodes(Type); ++i)
350 {
351 iBoundaryNodes += (int)BoundaryNodes.count(*itIndex);
352 ElemIndices.push_back(*itIndex);
353 ++itIndex;
354 }
355 // Filter out any faces which lie on the yarn boundary
356 if (iBoundaryNodes != (int)ElemIndices.size())
357 {
358 Face = FindFaceIndex(iYarn, ElemIndices);
359 Faces.push_back(Face);
360 }
361 }
362 }
363 }
364}
365
367{
368 CMesh VolumeMesh = m_YarnMeshes[iYarn];
369
371 VolumeMesh.RemoveUnreferencedNodes();
372
373 list<int>::iterator itIndex;
374 int i, iElementIndex, iType;
375 for (iType = 0; iType < CMesh::NUM_ELEMENT_TYPES; ++iType)
376 {
377 if ( iType == CMesh::POLYGON )
378 continue;
380 list<int> &Indices = VolumeMesh.GetIndices(Type);
381 for (itIndex = Indices.begin(), iElementIndex=0; itIndex != Indices.end(); ++iElementIndex)
382 {
383 vector<int> VolIndices;
384 for (i=0; i<CMesh::GetNumNodes(Type); ++i)
385 {
386 VolIndices.push_back(*(itIndex++));
387 }
388 set<int> CommonIndices = GetCommonIndices(SurfIndices, VolIndices);
389 if (CommonIndices.size() == SurfIndices.size())
390 {
391 // Bingo, we have a match...
392 ELEMENT_FACE Face;
393 Face.ElementType = Type;
394 Face.iElementIndex = iElementIndex;
395 Face.iFaceIndex = GetFaceIndex(Type, CommonIndices);
396 Face.iYarn = iYarn;
397 return Face;
398 }
399 }
400 }
401 // We should never reach this point
402 assert(false);
403 return ELEMENT_FACE();
404}
405
406int CSimulationAbaqus::GetFaceIndex(CMesh::ELEMENT_TYPE ElemType, const set<int> &NodeIndices)
407{
408 // Face indices taken from abaqus manual 22.1.4 Three-dimensional solid element library
409 switch (ElemType)
410 {
411 case CMesh::HEX:
412 if (NodeIndices.count(0) && NodeIndices.count(1) && NodeIndices.count(2) && NodeIndices.count(3))
413 return 0;
414 if (NodeIndices.count(4) && NodeIndices.count(5) && NodeIndices.count(6) && NodeIndices.count(7))
415 return 1;
416 if (NodeIndices.count(0) && NodeIndices.count(1) && NodeIndices.count(4) && NodeIndices.count(5))
417 return 2;
418 if (NodeIndices.count(1) && NodeIndices.count(2) && NodeIndices.count(5) && NodeIndices.count(6))
419 return 3;
420 if (NodeIndices.count(2) && NodeIndices.count(3) && NodeIndices.count(6) && NodeIndices.count(7))
421 return 4;
422 if (NodeIndices.count(3) && NodeIndices.count(0) && NodeIndices.count(7) && NodeIndices.count(4))
423 return 5;
424 break;
425 case CMesh::WEDGE:
426 // Note face indices 0 and 1 are switched because of the diference in local node numbering in
427 // ABAQUS and VTK
428 if (NodeIndices.count(0) && NodeIndices.count(1) && NodeIndices.count(2))
429 return 1;
430 if (NodeIndices.count(3) && NodeIndices.count(4) && NodeIndices.count(5))
431 return 0;
432 if (NodeIndices.count(0) && NodeIndices.count(1) && NodeIndices.count(3) && NodeIndices.count(4))
433 return 2;
434 if (NodeIndices.count(1) && NodeIndices.count(2) && NodeIndices.count(4) && NodeIndices.count(5))
435 return 3;
436 if (NodeIndices.count(2) && NodeIndices.count(0) && NodeIndices.count(5) && NodeIndices.count(3))
437 return 4;
438 break;
439 }
440 assert(false);
441 return -1;
442}
443
444set<int> CSimulationAbaqus::GetCommonIndices(const vector<int> &SurfIndices, const vector<int> &VolIndices)
445{
446 set<int> Common;
447 vector<int>::const_iterator itSurf;
448 vector<int>::const_iterator itVol;
449 int i;
450 for (itSurf = SurfIndices.begin(); itSurf != SurfIndices.end(); ++itSurf)
451 {
452 for (itVol = VolIndices.begin(), i=0; itVol != VolIndices.end(); ++itVol, ++i)
453 {
454 if (*itSurf == *itVol)
455 {
456 Common.insert(i);
457 }
458 }
459 }
460 return Common;
461}
462
464{
465 // In TexGen we have 1 mesh for each yarn and each mesh has
466 // a seperate list for each element type.
467 // In ABAQUS we have 1 mesh for the entire model and element
468 // indices are shared for all element types.
469 // We need to convert TexGen indices to ABAQUS indices. In
470 // order to do this we need an index offset for each element
471 // type and yarn number. This is what this code below does
472 int i, iNumYarns = (int)m_YarnMeshes.size();
473 int iType;
474 int iElemIndexOffset = 0;
475 m_ElementIndexOffsets.clear();
476 for (iType = 0; iType < CMesh::NUM_ELEMENT_TYPES; ++iType)
477 {
479 for (i=0; i<iNumYarns; ++i)
480 {
481 m_ElementIndexOffsets[i][Type] = iElemIndexOffset;
482 iElemIndexOffset += m_YarnMeshes[i].GetNumElements(Type);
483 }
484 }
485 m_NodeIndexOffsets.clear();
486 int iNodeIndexOffset = 0;
487 for (i=0; i<iNumYarns; ++i)
488 {
489 m_NodeIndexOffsets[i] = iNodeIndexOffset;
490 iNodeIndexOffset += m_YarnMeshes[i].GetNumNodes();
491 }
492}
493
495{
496 return m_ElementIndexOffsets[iYarn][ElemType] + iIndex;
497}
498
500{
501 return GetGlobalElementIndex(Face.iYarn, Face.ElementType, Face.iElementIndex);
502}
503
505{
506 return m_NodeIndexOffsets[iYarn] + iIndex;
507}
508
509void CSimulationAbaqus::CreateMaterials(ostream &Output, string Filename)
510{
511 string ElementDataFilename = Filename;
512 ElementDataFilename.replace(ElementDataFilename.end()-4, ElementDataFilename.end(), ".eld");
513 Output << "*****************" << endl;
514 Output << "*** MATERIALS ***" << endl;
515 Output << "*****************" << endl;
516
517 map<string, pair<CObjectContainer<CMaterial>, CObjectContainer<CMaterial> > > Materials = m_Materials.GetMaterials();
518 map<int, string> MaterialAssignements = m_Materials.GetMaterialAssignements();
519
520 map<string, pair<CObjectContainer<CMaterial>, CObjectContainer<CMaterial> > >::iterator itMaterial;
521 for (itMaterial = Materials.begin(); itMaterial != Materials.end(); ++itMaterial)
522 {
523 Output << "*Material, Name=" << itMaterial->first << endl;
524 if ( itMaterial->second.first->GetConstants().size() == 2 )
525 Output << itMaterial->second.first->GetAbaqusCommands();
526 else
527 Output << itMaterial->second.first->GetAbaqusCommands( "ENGINEERING CONSTANTS" );
528 Output << "*Damping, alpha= 3.75e+6" << endl;
529 Output << "*Density" << endl;
530 Output << "1.37e-09," << endl;
531 Output << "*DepVar" << endl;
532 Output << "5" << endl;
533 }
534 int i, iNumYarns = (int)m_YarnMeshes.size();
535 string MatName;
536 for (i = 0; i < iNumYarns; ++i)
537 {
538 if (MaterialAssignements.count(i))
539 MatName = MaterialAssignements[i];
540 else
541 MatName = Materials.begin()->first;
542 Output << "*Solid Section, ElSet=Yarn" << i << ", Material=" << MatName << ", Orientation=TexGenOrientations, controls=HourglassEnhanced" << endl;
543 Output << "1.0," << endl;
544 }
545
546 Output << "*Section Controls, Name=HourglassEnhanced, Hourglass=Enhanced, SECOND ORDER ACCURACY=YES" << endl;
547 Output << "** Note: Additional element data are stored as a depvars:" << endl;
548 WriteElementsHeader( Output );
549 Output << "*Initial Conditions, Type=Solution, Input=" << StripPath(ElementDataFilename) << endl;
550}
551
552void CSimulationAbaqus::CreateSurfaces(ostream &Output, map< string, vector<ELEMENT_FACE> > &SurfaceDefinitions)
553{
554 // Now output the surface definitions
555 Output << "***************************" << endl;
556 Output << "*** SURFACE DEFINITIONS ***" << endl;
557 Output << "***************************" << endl;
558 vector<ELEMENT_FACE>::iterator itFace;
559
560 map<string, vector<ELEMENT_FACE> >::iterator itSurfDef;
561
562 for (itSurfDef = SurfaceDefinitions.begin(); itSurfDef != SurfaceDefinitions.end(); ++itSurfDef)
563 {
564 Output << "*Surface, Name=" << itSurfDef->first << ", Type=Element" << endl;
565 for (itFace = itSurfDef->second.begin(); itFace != itSurfDef->second.end(); ++itFace)
566 {
567 // ABAQUS is 1 based, so add 1
568 Output << GetGlobalElementIndex(*itFace)+1 << ", S" << itFace->iFaceIndex+1 << endl;
569 }
570 }
571}
572
573void CSimulationAbaqus::CreateContacts(ostream &Output, const CTextile &Textile)
574{
575 Output << "***************************" << endl;
576 Output << "*** CONTACT DEFINITIONS ***" << endl;
577 Output << "***************************" << endl;
578
579 const CTextileWeave* pWeave = dynamic_cast<const CTextileWeave*>(&Textile);
580 const CTextile3DWeave* p3DWeave = dynamic_cast<const CTextile3DWeave*>(&Textile);
581 if (pWeave)
582 {
583 CreateContacts(Output, *pWeave);
584 }
585 else if (p3DWeave)
586 {
587 Output << "*** WARNING: Contacts are only created for upper and lower surfaces." << endl;
588 Output << "*** Any contacts between binder yarns and sides of warp and weft" << endl;
589 Output << "*** yarns must be specified manually" << endl;
590 CreateContacts(Output, *p3DWeave);
591 }
592 else
593 {
594 Output << "*** WARNING: TexGen was unable to create contact definitions automatically" << endl;
595 Output << "*** because the textile is not of type CTextileWeave" << endl;
596 }
597
598 // Create contacts with the plate
600 {
601 Output << "*Surface Interaction, Name=Plate" << endl;
603 Output << m_PlateInteraction->GetAbaqusCommands();
604 int i;
605 for (i=0; i<Textile.GetNumYarns(); ++i)
606 {
607 if ( m_bWholeSurfaces )
608 {
609 CreateContact(Output, "YarnSurf" + stringify(i), "TopPlate", "Plate");
610 CreateContact(Output, "YarnSurf" + stringify(i), "BottomPlate", "Plate");
611 }
612 else
613 {
614 CreateContact(Output, "Yarn" + stringify(i) + "Upper", "TopPlate", "Plate");
615 CreateContact(Output, "Yarn" + stringify(i) + "Lower", "BottomPlate", "Plate");
616 }
617 }
618 }
619}
620
621void CSimulationAbaqus::CreateContacts(ostream &Output, const CTextileWeave &Weave)
622{
624 Output << m_YarnInteraction->GetAbaqusCommands();
625 set<pair<int, int> > Contacts;
626 int i, j, k;
627 for (i=0; i<Weave.GetNumYYarns(); ++i)
628 {
629 for (j=0; j<Weave.GetNumXYarns(); ++j)
630 {
631 const vector<PATTERN2D> &Cell = Weave.GetCell(i, j);
632 for (k=1; k<(int)Cell.size(); ++k)
633 {
634 Contacts.insert(make_pair(Weave.GetYarnIndex(i, j, k-1), Weave.GetYarnIndex(i, j, k)));
635 }
636 }
637 }
638 OutputContacts( Output, Contacts );
639}
640
641void CSimulationAbaqus::CreateContacts(ostream &Output, const CTextile3DWeave &Weave)
642{
644 Output << m_YarnInteraction->GetAbaqusCommands();
645 set<pair<int, int> > Contacts;
646 int i, j, k;
647 for (i=0; i<Weave.GetNumYYarns(); ++i)
648 {
649 for (j=0; j<Weave.GetNumXYarns(); ++j)
650 {
651 const vector<PATTERN3D> &Cell = Weave.GetCell(i, j);
652 for (k=1; k<(int)Cell.size(); ++k)
653 {
654 if ( Cell[k-1] != PATTERN3D_NOYARN && Cell[k] != PATTERN3D_NOYARN )
655 Contacts.insert(make_pair(Weave.GetYarnIndex(i, j, k-1), Weave.GetYarnIndex(i, j, k)));
656 }
657 }
658 }
659 OutputContacts( Output, Contacts );
660}
661
662void CSimulationAbaqus::OutputContacts( ostream &Output, set<pair<int, int> > &Contacts )
663{
664 set<pair<int, int> >::iterator itContact;
665 for (itContact = Contacts.begin(); itContact != Contacts.end(); ++itContact)
666 {
667 if ( m_bWholeSurfaces )
668 CreateContact(Output, "YarnSurf" + stringify(itContact->first),
669 "YarnSurf" + stringify(itContact->second) , "Yarn");
670 else
671 CreateContact(Output, "Yarn" + stringify(itContact->first) + "Upper",
672 "Yarn" + stringify(itContact->second) + "Lower", "Yarn");
673 }
674}
675
677{
678 Output << "**************************" << endl;
679 Output << "*** COMPRESSION PLATES ***" << endl;
680 Output << "**************************" << endl;
681
682 vector<CMesh>::iterator itMesh;
683 pair<XYZ, XYZ> YarnAABB;
684 pair<XYZ, XYZ> TextileAABB;
685 for (itMesh = m_YarnMeshes.begin(); itMesh != m_YarnMeshes.end(); ++itMesh)
686 {
687 YarnAABB = itMesh->GetAABB(m_dInitialPlateGap);
688 if (itMesh == m_YarnMeshes.begin())
689 {
690 TextileAABB = YarnAABB;
691 }
692 else
693 {
694 TextileAABB.first = Min(TextileAABB.first, YarnAABB.first);
695 TextileAABB.second = Max(TextileAABB.second, YarnAABB.second);
696 }
697 }
698 double dWidth = TextileAABB.second.x-TextileAABB.first.x;
699 double dMinX = TextileAABB.first.x - dWidth;
700 double dMaxX = TextileAABB.second.x + dWidth;
701 double dLocalY, dZ;
702 int i, iDummyNodeNum;
703 string Name;
704 m_TopPlatePos.z = TextileAABB.second.z;
705 m_BottomPlatePos.z = TextileAABB.first.z;
706 XYZ GeneratorDir;
707 for (i=0; i<2; ++i)
708 {
709 if (i==0)
710 {
711 Name = "TopPlate";
712 dZ = m_TopPlatePos.z;
713 GeneratorDir = XYZ(0, -1, 0); // Make sure the normal is correct
714 dLocalY = -dZ;
715 }
716 else
717 {
718 Name = "BottomPlate";
719 dZ = m_BottomPlatePos.z;
720 GeneratorDir = XYZ(0, 1, 0); // Make sure the normal is correct
721 dLocalY = dZ;
722 }
723 iDummyNodeNum = ++m_iTotalNumNodes; // Note this is now a 1-based node index
724 Output << "*Node" << endl;
725 Output << iDummyNodeNum << ", 0, 0, " << dZ << endl;
726 Output << "*NSet, NSet=" << Name << endl;
727 Output << iDummyNodeNum << endl;
728 Output << "*Surface, Type=Cylinder, Name=" << Name << endl;
729 Output << "0, 0, 0, 1, 0, 0" << endl;
730 Output << GeneratorDir << endl;
731 Output << "Start, " << dMinX << ", " << dLocalY << endl;
732 Output << "Line, " << dMaxX << ", " << dLocalY << endl;
733 Output << "*Rigid Body, Analytical Surface=" << Name << ", Ref Node=" << Name << endl;
734 }
735}
736
738{
739 pair<XYZ, XYZ> AABB = Mesh.GetAABB();
740
741 XYZ Center = 0.5*(AABB.first + AABB.second);
742
743 return Mesh.GetClosestNode(Center);
744}
745
746void CSimulationAbaqus::CreatePeriodicBoundaries(ostream &Output, const CDomain &TextileDomain)
747{
748 //PROFILE_FUNC()
749 Output << "************************************" << endl;
750 Output << "*** PERIODIC BOUNDARY CONDITIONS ***" << endl;
751 Output << "************************************" << endl;
752
753 vector<pair<int, int> > NodePairs;
754 int i, j;
755
756 pair<XYZ, XYZ> DomainAABB = TextileDomain.GetMesh().GetAABB();
757 vector<XYZ> DomainSize;
758 DomainSize.push_back(XYZ(DomainAABB.second.x - DomainAABB.first.x, 0,0));
759 DomainSize.push_back(XYZ(0, DomainAABB.second.y - DomainAABB.first.y, 0));
760 DomainSize.push_back(XYZ(0, 0, DomainAABB.second.z - DomainAABB.first.z));
761
762 for ( i = 0; i < (int)DomainSize.size(); ++i )
763 {
764 NodePairs.clear();
765 m_TextileMesh.GetNodePairs(DomainSize[i], NodePairs);
766 if ( NodePairs.size() > 0 )
767 {
768 CreateSet(Output, "Bound" + stringify(i), NodePairs);
769 int iDummyNodeNum = ++m_iTotalNumNodes; // Note this is now a 1-based node index
770 Output << "*Node" << endl;
771 Output << iDummyNodeNum << ", 0, 0, 0" << endl;
772 Output << "*NSet, NSet=Dummy" << i << endl;
773 Output << iDummyNodeNum << endl;
774 for (j=0; j<3; ++j)
775 {
776 Output << "*Equation\n3\n";
777 Output << "Bound" << i << "A, " << j+1 << ", 1.0, Bound" << i << "B, " << j+1 << ", -1.0, Dummy" << i << ", " << j+1 << ", 1.0" << endl;
778 }
779 }
780 }
781
782 pair<XYZ, XYZ> Domain = m_TextileMesh.GetAABB();
783
784 Output << "*** Nodes containing domain AABB ***" << endl;
785 Output << "*Node" << endl;
786 Output << ++m_iTotalNumNodes << ", " << Domain.first.x << ", " << Domain.first.y << ", " << Domain.first.z << endl;
787 Output << ++m_iTotalNumNodes << ", " << Domain.second.x << ", " << Domain.second.y << ", " << Domain.second.z << endl;
788 Output << "*NSet, NSet=Domain" << endl;
789 Output << m_iTotalNumNodes-1 << ", " << m_iTotalNumNodes << endl;
790}
791
792void CSimulationAbaqus::CreateStep(ostream &Output)
793{
794 Output << "************" << endl;
795 Output << "*** INTERACTION PROPERTIES ***" << endl;
796 Output << "************" << endl;
797 Output << "*Surface Interaction, name=YARN" << endl;
798 Output << "*Friction" << endl;
799 Output << "0.112," << endl;
800 Output << "*Surface Behavior, pressure-overclosure=HARD" << endl;
801
802 Output << "************" << endl;
803 Output << "*** STEP ***" << endl;
804 Output << "************" << endl;
805 Output << "*Step, NLGeom=Yes" << endl;
806 Output << "*Dynamic, Explicit" << endl;
807 Output << ",2.5e-5" << endl;
808 Output << "*Bulk Viscosity" << endl;
809 Output << "0.06, 1.2" << endl;
810 if (!m_StaticStepParameters.empty())
811 Output << m_StaticStepParameters << endl;
812}
813
814void CSimulationAbaqus::CreateBoundary(ostream &Output, CLinearTransformation Deformation, const vector<int> &YarnCenterNodes, const vector<XYZ> &Repeats)
815{
816 Output << "*Output, History, Variable=PRESELECT" << endl;
817 Output << "*Output, Field, Variable=PRESELECT" << endl;
818 Output << "*Element Output" << endl;
819 Output << "SDV" << endl;
820// Output << "*Node Print" << endl;
821// Output << "U1, U2, U3" << endl;
822
823 Output << "*Boundary" << endl;
824 Output << "*Amplitude, name=Amp-1" << endl;
825 Output << "0., 0., 2.5e-05, 1." << endl;
826 Output << "*Boundary, amplitude=Amp-1" << endl;
827 Output << "*** Constrain the nodes closest to the geometrical center of each yarns" << endl;
828// Output << GetCenterNode(m_TextileMesh)+1 << ", 1, 3, 0" << endl;
829 XYZ Position, Displacement;
830 vector<int>::const_iterator itCenterNode;
831 int i, j;
832 for (itCenterNode = YarnCenterNodes.begin(); itCenterNode != YarnCenterNodes.end(); ++itCenterNode)
833 {
834 Position = m_TextileMesh.GetNode(*itCenterNode);
835 Displacement = Deformation * Position - Position;
836 for (j=0; j<3; ++j)
837 {
838 Output << (*itCenterNode)+1 << ", " << j+1 << ", " << j+1 << ", " << Displacement[j] << endl;
839 }
840 }
842 {
843 Output << "*** Constrain the plates" << endl;
844 XYZ TopDisp = Deformation * m_TopPlatePos - m_TopPlatePos;
845 XYZ BottomDisp = Deformation * m_BottomPlatePos - m_BottomPlatePos;
846 for (j=0; j<3; ++j)
847 {
848 Output << "TopPlate" << ", " << j+1 << ", " << j+1 << ", " << TopDisp[j] << endl;
849 Output << "BottomPlate" << ", " << j+1 << ", " << j+1 << ", " << BottomDisp[j] << endl;
850 }
851 Output << "TopPlate" << ", 4, 6, 0" << endl;
852 Output << "BottomPlate" << ", 4, 6, 0" << endl;
853 }
854 XYZ Relative;
855 Output << "*** Apply the repeat vector constraints" << endl;
856 for (i=0; i<(int)Repeats.size(); ++i)
857 {
858 Relative = Deformation * Repeats[i] - Repeats[i];
859 for (j=0; j<3; ++j)
860 {
861 Output << "Dummy" << i << ", " << j+1 << ", " << j+1 << ", " << Relative[j] << endl;
862 }
863 }
864 Output << "*End Step" << endl;
865}
866void CSimulationAbaqus::CreateContact(ostream &Output, string Name1, string Name2, string InteractionName)
867{
868 Output << "*Contact Pair, Interaction=" << InteractionName << endl;
869 Output << Name1 << ", " << Name2 << endl;
870}
871void CSimulationAbaqus::CreateSet(ostream &Output, string Name, const vector<pair<int, int> > &NodePairs)
872{
873 vector<pair<int, int> >::const_iterator itPair;
874 vector<int> GroupA;
875 vector<int> GroupB;
876 for (itPair = NodePairs.begin(); itPair != NodePairs.end(); ++itPair)
877 {
878 GroupA.push_back(itPair->first);
879 GroupB.push_back(itPair->second);
880 }
881 CreateSet(Output, NODE_SET, Name + "A", GroupA, true);
882 CreateSet(Output, NODE_SET, Name + "B", GroupB, true);
883}
884
885void CSimulationAbaqus::CreateSet(ostream &Output, SET_TYPE Type, string Name, vector<int> &Indices, bool bUnSorted)
886{
887 switch (Type)
888 {
889 case NODE_SET:
890 Output << "*NSet, NSet=" << Name;
891 break;
892 case ELEMENT_SET:
893 Output << "*ElSet, ElSet=" << Name;
894 break;
895 }
896 if (bUnSorted)
897 {
898 Output << ", Unsorted";
899 }
900
901 Output << endl;
902
903 // Increase the indices by 1 because abaqus is 1 based
904 vector<int>::iterator itIndex;
905 for (itIndex = Indices.begin(); itIndex != Indices.end(); ++itIndex)
906 {
907 *itIndex += 1;
908 }
909 WriteValues(Output, Indices, 16);
910}
911
913{
914 m_YarnInteraction = CKeywordInteraction(AbaqusCommands);
915}
916
918{
919 m_PlateInteraction = CKeywordInteraction(AbaqusCommands);
920}
921
922void CSimulationAbaqus::SetStaticStepParameters(double dInitTimeInc, double dTimePeriod, double dMinTimeInc, double dMaxTimeInc)
923{
924 m_StaticStepParameters = stringify(dInitTimeInc) + ", ";
925 m_StaticStepParameters += stringify(dTimePeriod) + ", ";
926 m_StaticStepParameters += stringify(dMinTimeInc) + ", ";
927 m_StaticStepParameters += stringify(dMaxTimeInc);
928}
929
930
931double CSimulationAbaqus::GetSectionArea( vector<int> &Section, CMesh &Mesh )
932{
933 // area3D_Polygon(): computes the area of a 3D planar polygon
934 // From: http://softsurfer.com/Archive/algorithm_0101/algorithm_0101.htm#area3D_Polygon
935// Input: int n = the number of vertices in the polygon
936// Point* V = an array of n+2 vertices in a plane
937// with V[n]=V[0] and V[n+1]=V[1]
938// Point N = unit normal vector of the polygon's plane
939// Return: the (float) area of the polygon
940
941 vector<int>::iterator itSection;
942 vector<XYZ> Points;
943
944 for ( itSection = Section.begin(); itSection != Section.end(); ++itSection )
945 {
946 Points.push_back( Mesh.GetNode( *itSection ) );
947 }
948
949 int iNumNodes = (int)Points.size()-1;
950 Points.push_back( Points[1] );
951
952 double an, ax, ay, az; // abs value of normal and its coords
953 XYZ Normal = CrossProduct( (Points[0] - Points[1]), (Points[2] - Points[1]) );
954 an = GetLength( Normal );
955 Normal /= an; // Normalise
956
957 double area = 0;
958 int i, j, k; // loop indices
959 int coord; // coord to ignore: 1=x, 2=y, 3=z
960
961
962
963 // select largest abs coordinate to ignore for projection
964 ax = fabs(Normal.x); // abs x-coord
965 ay = fabs(Normal.y); // abs y-coord
966 az = fabs(Normal.z); // abs z-coord
967
968 coord = 3; // ignore z-coord
969 if (ax > ay) {
970 if (ax > az) coord = 1; // ignore x-coord
971 }
972 else if (ay > az) coord = 2; // ignore y-coord
973
974 // compute area of the 2D projection
975 for (i=1, j=2, k=0; i<=iNumNodes; i++, j++, k++)
976 switch (coord) {
977 case 1:
978 area += (Points[i].y * (Points[j].z - Points[k].z));
979 continue;
980 case 2:
981 area += (Points[i].x * (Points[j].z - Points[k].z));
982 continue;
983 case 3:
984 area += (Points[i].x * (Points[j].y - Points[k].y));
985 continue;
986 }
987
988 // scale to get area before projection
989 switch (coord) {
990 case 1:
991 area /= (2*ax);
992 //area *= (an / (2*ax));
993 break;
994 case 2:
995 area /= (2*ay);
996 //area *= (an / (2*ay));
997 break;
998 case 3:
999 area /= (2*az);
1000 //area *= (an / (2*az));
1001 }
1002 return fabs(area);
1003}
1004
1005double CSimulationAbaqus::GetSectionVolumeFraction( double Area, CTextile &Textile, int Yarn )
1006{
1007 double dVolumeFraction;
1008 CYarn* pYarn = Textile.GetYarn(Yarn);
1009 if (pYarn->GetFibreDistribution())
1010 {
1011 double dFibreArea = pYarn->GetFibreArea(Textile.GetGeometryScale()+"^2");
1012 if (dFibreArea == 0)
1013 dFibreArea = Textile.GetFibreArea(Textile.GetGeometryScale()+"^2");
1014 dVolumeFraction = pYarn->GetFibreDistribution()->GetVolumeFraction(Area, dFibreArea, Yarn);
1015 }
1016 else
1017 {
1018 dVolumeFraction = -1;
1019 }
1020 return dVolumeFraction;
1021}
1022
1023void CSimulationAbaqus::CreateMidPointVolumeFractions( vector<SECTION_VF_DATA> &VFData, vector<SECTION_VF_DATA> &VFMidData )
1024{
1025 vector<SECTION_VF_DATA>::iterator itData;
1026
1027 SECTION_VF_DATA PrevData = VFData[0];
1028 for ( itData = VFData.begin(); itData != VFData.end(); ++itData )
1029 {
1030 if ( itData == VFData.begin())
1031 {
1032 PrevData = *(itData);
1033 }
1034 else
1035 {
1036 SECTION_VF_DATA Data;
1037 Data.iMin = PrevData.iMin; // Set minimum and maximum indices of sections bounding the mid-point
1038 Data.iMax = itData->iMax;
1039 Data.dVolumeFraction = (PrevData.dVolumeFraction + itData->dVolumeFraction) / 2.0;
1040 VFMidData.push_back( Data );
1041 PrevData = *(itData);
1042 }
1043 }
1044}
1045
1046void CSimulationAbaqus::GetElementVolumeFractions( vector<POINT_INFO> &ElementsInfo, vector<SECTION_VF_DATA> &MidVFData )
1047{
1048 list<int>::const_iterator itIndex;
1049 vector<SECTION_VF_DATA>::iterator itData;
1050 int i, ElementIndex = 0;
1051 for (i = 0; i < CMesh::NUM_ELEMENT_TYPES; ++i)
1052 {
1053 int iNumNodes = CMesh::GetNumNodes((CMesh::ELEMENT_TYPE)i);
1054 if ( iNumNodes != -1 ) // Don't want to get volume fraction of POLYGON sections
1055 {
1056 for ( itIndex = m_TextileMesh.GetIndices((CMesh::ELEMENT_TYPE)i).begin(); itIndex != m_TextileMesh.GetIndices((CMesh::ELEMENT_TYPE)i).end(); )
1057 {
1058 vector<int> Indices;
1059 int j;
1060 for ( j = 0; j < iNumNodes; ++j )
1061 {
1062 Indices.push_back( *(itIndex++) );
1063 }
1064 // Find which mid-section corresponds to current element
1065 for ( itData = MidVFData.begin(); itData != MidVFData.end(); ++itData )
1066 {
1067 int iNum = 0;
1068 vector<int>::iterator itIndices;
1069 for ( itIndices = Indices.begin(); itIndices != Indices.end(); ++itIndices )
1070 {
1071 iNum++;
1072 if ( *itIndices < itData->iMin || *itIndices > itData->iMax )
1073 break;
1074 }
1075
1076 if ( iNum == iNumNodes )
1077 {
1078 ElementsInfo[ElementIndex++].dVolumeFraction = itData->dVolumeFraction;
1079 break;
1080 }
1081 }
1082
1083 }
1084 }
1085 }
1086}
1087
1088void CSimulationAbaqus::GetSectionVolumeFractions(CTextile &Textile, vector<SECTION_VF_DATA> &VolFractionData, int iYarn )
1089{
1090 list<int> &PolygonIndices = m_YarnMeshes[iYarn].GetIndices( CMesh::POLYGON );
1091 list<int>::iterator itInt;
1092 for ( itInt = PolygonIndices.begin(); itInt != PolygonIndices.end(); )
1093 {
1094 SECTION_VF_DATA VolFData;
1095 vector<int> Section;
1096 Section.clear();
1097 int StartIndex = *(itInt);
1098 double Area;
1099 VolFData.iMin = VolFData.iMax = StartIndex;
1100
1101 // Get the min & max indices of the section and store the indices
1102 do {
1103 if ( *(itInt) < VolFData.iMin )
1104 VolFData.iMin = *(itInt);
1105 if ( *(itInt) > VolFData.iMax )
1106 VolFData.iMax = *(itInt);
1107 Section.push_back( *(itInt++) );
1108 } while ( *(itInt)!= StartIndex );
1109
1110 if ( *(itInt) < VolFData.iMin )
1111 VolFData.iMin = *(itInt);
1112 if ( *(itInt) > VolFData.iMax )
1113 VolFData.iMax = *(itInt);
1114 Section.push_back( *(itInt++) );
1115
1116 Area = GetSectionArea( Section, m_YarnMeshes[iYarn] );
1117 VolFData.dVolumeFraction = GetSectionVolumeFraction( Area, Textile, iYarn );
1118 VolFData.iMin = GetGlobalNodeIndex( iYarn, VolFData.iMin );
1119 VolFData.iMax = GetGlobalNodeIndex( iYarn, VolFData.iMax );
1120 VolFractionData.push_back( VolFData );
1121 }
1122}
#define TGERROR(MESSAGE)
Macros used to report the file name and line number to the TexGenError and TexGenLog functions.
Definition: Logger.h:29
#define TGLOG(MESSAGE)
Definition: Logger.h:36
Class used to adjust small interferences in the fibre volume mesh.
void AdjustSectionMeshes(CTextile &Textile, vector< CMesh > &YarnMeshes)
Adjust yarns to interpolate between section meshes and change these to reflect intersection adjustmen...
bool AdjustMesh(CTextile &Textile, vector< CMesh > &YarnMeshes, double Tolerance)
Top level function to adjust nodes on all yarns.
Abstract base class representing the domain in which a textile cell may lie.
Definition: Domain.h:34
const CMesh & GetMesh() const
Get the mesh representing the domain as a surface mesh.
Definition: Domain.h:73
virtual double GetVolumeFraction(const vector< XY > &Section, double dFibreArea, XY Location, int YarnIndex=-1) const =0
Get the volume fraction for a given location.
Represents a linear transformation as a 3x3 matrix.
Defines the nodes and elements of a surface or volume mesh.
Definition: Mesh.h:58
int GetNumNodes() const
Return the number of nodes.
Definition: Mesh.cpp:2646
void InsertMesh(const CMesh &Mesh, XYZ Offset=XYZ(0, 0, 0))
Add the contents of Mesh to this mesh.
Definition: Mesh.cpp:93
vector< pair< int, int > > GetNodePairs(XYZ Vector, const double Tolerance=1e-6) const
Return a list of node pairs (A, B) where A == B + Vector.
Definition: Mesh.cpp:463
bool SaveToABAQUS(string Filename, const vector< POINT_INFO > *pElementInfo=NULL, bool bCreateStep=true, bool bCreateMaterial=true, int iElementType=0)
Save the mesh to ABAQUS input file format with information such as yarn tangents.
Definition: Mesh.cpp:2089
const XYZ & GetNode(int iIndex) const
Get the node with given ID.
Definition: Mesh.cpp:2636
int RemoveUnreferencedNodes()
Remove nodes that are not referenced by any elements.
Definition: Mesh.cpp:687
static int GetNumNodes(ELEMENT_TYPE Type)
Get the number of nodes a particular element type contains.
Definition: Mesh.h:81
int GetClosestNode(XYZ Position) const
Get the index of the node closest to the given position space.
Definition: Mesh.cpp:532
void RemoveElementType(ELEMENT_TYPE Type)
Remove elements of given type.
Definition: Mesh.cpp:723
const list< int > & GetIndices(ELEMENT_TYPE ElemType) const
Get the element indices of a given element type.
Definition: Mesh.cpp:2671
ELEMENT_TYPE
Each element type is represented by a unique integer value.
Definition: Mesh.h:66
@ NUM_ELEMENT_TYPES
Definition: Mesh.h:77
@ POLYGON
Definition: Mesh.h:76
pair< XYZ, XYZ > GetAABB(double dGrowDistance=0) const
Get an axis aligned bounding box for the mesh.
Definition: Mesh.cpp:340
void Clear()
Empty mesh nodes and indices.
Definition: Mesh.cpp:1448
void ConvertToSurfaceMesh()
Convert a volume mesh into a surface mesh (interior surfaces are elliminated)
Definition: Mesh.cpp:569
Object container to help handle memory management issues.
double GetFibreArea(string Units="m^2") const
Get the area occupied by fibres given fibre diameter and number of fibres.
Definition: Properties.cpp:251
Represents a surface interaction as a string of ABAQUS keywords.
void CreateStep(ostream &Output)
Create a step.
void CreateContact(ostream &Output, string Name1, string Name2, string InteractionName)
Create a contact pair from two surface definitions.
void CreateCompressionPlates(ostream &Output)
Create two rigid body analytical planes: one above and one below.
void CreateMaterials(ostream &Output, string Filename)
Create the materials for the yarns.
void GetYarnSurfaces(int iYarn, const vector< XYZ > &Repeats, vector< ELEMENT_FACE > &UpperFaces, vector< ELEMENT_FACE > &LowerFaces)
Get a list of faces which make up the surfaces of a yarn.
set< int > GetCommonIndices(const vector< int > &SurfIndices, const vector< int > &VolIndices)
Find the common indices between a surface element and a volume element.
void CreatePeriodicBoundaries(ostream &Output, const CDomain &Domain)
Create a step with given deformation.
int GetGlobalNodeIndex(int iYarn, int iIndex)
Get the global element index of a given face.
void GetYarnSurface(int iYarn, const vector< XYZ > &Repeats, vector< ELEMENT_FACE > &Faces)
Get a list of faces which make up the surface of a yarn.
map< YarnNumber, int > m_NodeIndexOffsets
CTextileMaterials m_Materials
void SetStaticStepParameters(double dInitTimeInc=0, double dTimePeriod=0, double dMinTimeInc=0, double dMaxTimeInc=0)
int GetGlobalElementIndex(int iYarn, CMesh::ELEMENT_TYPE ElemType, int iIndex)
int GetFaceIndex(CMesh::ELEMENT_TYPE ElemType, const set< int > &NodeIndices)
void OutputContacts(ostream &Output, set< pair< int, int > > &Contacts)
Output the contact definitions.
void CreateMidPointVolumeFractions(vector< SECTION_VF_DATA > &VFData, vector< SECTION_VF_DATA > &VFMidData)
Create an array of volume fractions at the mid points between sections.
void GetElementVolumeFractions(vector< POINT_INFO > &ElementsInfo, vector< SECTION_VF_DATA > &MidVFData)
Save the volume fraction for a given element - taken to be at the centre of the element.
void CreateBoundary(ostream &Output, CLinearTransformation Deformation, const vector< int > &YarnCenterNodes, const vector< XYZ > &Repeats)
Create output request and boundary conditions with given deformation.
int GetCenterNode(const CMesh &Mesh)
Get the central node index of a given mesh.
void CreateContacts(ostream &Output, const CTextile &Textile)
Create the contact definitions.
void CreateSurfaces(ostream &Output, map< string, vector< ELEMENT_FACE > > &SurfaceDefinitions)
Create ABAQUS surface definitions.
void GetSectionVolumeFractions(CTextile &Textile, vector< SECTION_VF_DATA > &VolFractionData, int iYarn)
Get volume fraction of section saved in POLYGON mesh section.
double GetSectionVolumeFraction(double Area, CTextile &Textile, int Yarn)
Get the volume fraction based on a given area.
bool CreateAbaqusInputFile(CTextile &Textile, string Filename, bool bRegenerateMesh, int iElementType=0, bool bAdjustMesh=false, double Tolerance=0.0000001)
void CreateSurfaceDefinitions(int iNumYarns, const vector< XYZ > &Repeats, map< string, vector< ELEMENT_FACE > > &SurfaceDefinitions)
ELEMENT_FACE FindFaceIndex(int iYarn, const vector< int > &SurfIndices)
Given a surface element, find the volume element it belongs to along with its face index.
void CreateSet(ostream &Output, SET_TYPE Type, string Name, vector< int > &Indices, bool bUnSorted=false)
Output an element or node set from a list of indices.
void SetYarnSurfaceInteraction(string AbaqusCommands)
Assign a surface interaction to be used at contacts between yarns.
CObjectContainer< CSurfaceInteraction > m_PlateInteraction
CObjectContainer< CSurfaceInteraction > m_YarnInteraction
double GetSectionArea(vector< int > &Section, CMesh &Mesh)
Get the cross-sectional area of the yarn section.
map< YarnNumber, map< CMesh::ELEMENT_TYPE, int > > m_ElementIndexOffsets
void BuildIndexOffsets()
Populate m_IndexOffsets parameter.
void SetPlateSurfaceInteraction(string AbaqusCommands)
Assign a surface interaction to be used at contacts between yarns and compaction plates.
vector< CLinearTransformation > m_DeformationSteps
Definition: Simulation.h:62
Represents a 3D woven textile.
int GetYarnIndex(int x, int y, int z) const
const vector< PATTERN3D > & GetCell(int x, int y) const
Represents a textile cell containing yarns.
Definition: Textile.h:39
const CDomain * GetDomain() const
Definition: Textile.h:287
int GetNumYarns() const
Definition: Textile.cpp:704
void AddVolumeToMesh(vector< CMesh > &YarnMeshes, bool bTrimToDomain=false)
Create volume mesh for each yarn in this textile and add to a vector of meshes.
Definition: Textile.cpp:301
void GetPointInformation(const vector< XYZ > &Points, vector< POINT_INFO > &PointsInfo, double dTolerance=1e-9)
Get useful information of a list of points.
Definition: Textile.cpp:410
const CYarn * GetYarn(int iIndex) const
Definition: Textile.cpp:693
map< string, pair< CObjectContainer< CMaterial >, CObjectContainer< CMaterial > > > GetMaterials()
Definition: Materials.h:75
map< int, string > GetMaterialAssignements()
Definition: Materials.h:76
void SetupMaterials(CTextile &Textile)
Set up a material for each unique set of material constants.
Definition: Materials.cpp:31
Represents a woven textile.
Definition: TextileWeave.h:41
int GetNumXYarns() const
Definition: TextileWeave.h:149
int GetYarnIndex(int x, int y, int z) const
const vector< PATTERN2D > & GetCell(int x, int y) const
int GetNumYYarns() const
Definition: TextileWeave.h:150
Represents a yarn consisting of master nodes, section and interpolation function.
Definition: Yarn.h:49
const CFibreDistribution * GetFibreDistribution() const
Definition: Yarn.h:451
const vector< XYZ > & GetRepeats() const
Definition: Yarn.h:448
Namespace containing a series of customised math operations not found in the standard c++ library.
std::string StripPath(std::string Filename)
Strip the path from the filename (e.g. "c:\folder\file.ext -> file.ext")
Definition: Misc.cpp:107
std::string ReplaceFilenameSpaces(std::string Filename)
Replaces spaces in filename with underscore.
Definition: Misc.cpp:130
void WriteElementsHeader(std::ostream &Output)
Write elements header for ABAQUS .eld files.
Definition: Misc.cpp:167
void WriteValues(std::ostream &Output, T &Values, int iMaxPerLine)
Definition: Misc.h:274
double Max(XYZ &Vector)
Get maximum element of vector and return it.
Definition: mymath.h:642
double GetLength(const XYZ &Point1, const XYZ &Point2)
Get the length between two points.
Definition: mymath.h:540
std::string stringify(const T &x, int iPrecision=12, bool bScientific=true)
Function to convert a value (e.g. int, double, etc...) to a string.
Definition: Misc.h:50
XYZ Min(const XYZ &P1, const XYZ &P2)
Given two points, return a new point who's coordinates are the smaller of the two.
Definition: mymath.h:1142
@ PATTERN3D_NOYARN
void AddExtensionIfMissing(std::string &Filename, std::string Extension)
Adds an extension to the filename if it is missing otherwise do nothing (e.g. picture -> picture....
Definition: Misc.cpp:116
XYZ CrossProduct(const XYZ &left, const XYZ &right)
Get the cross product of two vectors.
Definition: mymath.h:524
Struct for representing points in 3D space.
Definition: mymath.h:56
double z
Definition: mymath.h:57
double x
Definition: mymath.h:57
double y
Definition: mymath.h:57