TexGen
ShellElementExport.cpp
Go to the documentation of this file.
1/*=============================================================================
2TexGen: Geometric textile modeller.
3Copyright (C) 2019 Louise Brown
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 "TexGen.h"
22
23
24
25using namespace TexGen;
26CShellElementExport::CShellElementExport( bool bWholeSurfaces, bool bTrimSurface )
27: m_bWholeSurfaces( bWholeSurfaces )
28, m_bTrimSurface( bTrimSurface )
29{
30}
31
33{
34}
35
37{
38 TGLOG("Replacing spaces in filename with underscore for ABAQUS compatibility");
39 Filename = ReplaceFilenameSpaces( Filename );
40
41 int iNumYarns = Textile.GetNumYarns();
42 if (iNumYarns == 0)
43 return false;
44 const CDomain* pDomain = Textile.GetDomain();
45 if (!pDomain)
46 {
47 TGERROR("Unable to create ABAQUS input file: No domain specified");
48 return false;
49 }
50
51 m_YarnMeshes.clear();
52 int i;
53 m_YarnMeshes.resize(iNumYarns);
54
55
56 for (i=0; i<iNumYarns; ++i) // Create surface mesh for each yarn
57 {
58 CYarn* pYarn = Textile.GetYarn(i);
59 bool bMesh = false;
61 bMesh = pYarn->AddSurfaceToMesh( m_YarnMeshes[i], *pDomain );
62 else
63 bMesh = pYarn->AddSurfaceToMesh( m_YarnMeshes[i]);
64
65 if ( !bMesh )
66 {
67 TGERROR("Unable to create ABAQUS input file: Failed to create surface mesh for yarn " << i );
68 return false;
69 }
70 }
71
72 GetElementInfo( Textile );
73
74 for(i=0; i<iNumYarns; ++i) // Add meshes into single mesh
75 {
76 if ( !m_YarnMeshes[i].NodesEmpty() )
77 {
78 m_YarnMeshes[i].RemoveUnreferencedNodes();
80 }
81 }
82
83 // then assemble
84
86
87 m_SurfaceMesh.SaveToABAQUS(Filename, &m_ElementInfo, false, false );
88
89 ofstream Output(Filename.c_str(), ofstream::app );
90 // Output material properties
92 m_Materials->SetupMaterials( Textile );
93 m_Materials->OutputMaterials( Output, Textile.GetNumYarns(), false );
94 delete( m_Materials );
95
96 const vector<XYZ> &Repeats = Textile.GetYarn(0)->GetRepeats();
97 map<string, vector<pair<int, int>> > SurfaceDefinitions;
98
99 CreateSurfaceDefinitions( iNumYarns, Repeats, SurfaceDefinitions);
100 TGLOG("Creating surfaces");
101 CreateSurfaces(Output, SurfaceDefinitions);
102
103 CreateInteractions( Output );
104 CreateContacts(Output, Textile);
105
106 /*if ( m_iBoundaryConditions != NO_BOUNDARY_CONDITIONS )
107 {
108 m_PeriodicBoundaries->SetDomainSize( Textile.GetDomain()->GetMesh() );
109 if (SaveNodeSets() )
110 {
111 //ofstream Output(Filename.c_str(), ofstream::app );
112 Output << "*****************" << endl;
113 Output << "*** NODE SETS ***" << endl;
114 Output << "*****************" << endl;
115 Output << "** AllNodes - Node set containing all elements" << endl;
116 Output << "*NSet, NSet=AllNodes, Generate" << endl;
117 Output << "1, " << m_VolumeMesh.GetNumNodes() << ", 1" << endl;
118 m_PeriodicBoundaries->CreatePeriodicBoundaries( Output, m_VolumeMesh.GetNumNodes() + 1, Textile, m_iBoundaryConditions, false );
119 }
120 else
121 TGERROR("Unable to generate node sets");
122 }*/
123 return true;
124}
125
126void CShellElementExport::CreateSurfaceDefinitions( int iNumYarns, const vector<XYZ> &Repeats, map<string, vector<pair<int, int>> > &SurfaceDefinitions)
127{
128 for (int i=0; i<iNumYarns; ++i)
129 {
130 TGLOG("Creating yarn " << i << " surface definitions");
131 if ( m_bWholeSurfaces )
132 {
133 vector<pair<YarnNumber,int>> Elements;
134 GetYarnSurface( i, Elements );
135 SurfaceDefinitions["YarnSurf" + stringify(i)] = Elements;
136 }
137 else
138 {
139 vector<pair<int,int>> UpperFaces, LowerFaces;
140 GetYarnSurfaces( i, Repeats, UpperFaces, LowerFaces );
141 SurfaceDefinitions["Yarn" + stringify(i) + "Lower"] = LowerFaces;
142 SurfaceDefinitions["Yarn" + stringify(i) + "Upper"] = UpperFaces;
143 }
144 }
145}
146
147void CShellElementExport::GetYarnSurfaces(int iYarn, const vector<XYZ> &Repeats, vector<pair<int,int>> &UpperFaces, vector<pair<int,int>> &LowerFaces )
148{
149 CMesh SurfaceMesh = m_YarnMeshes[iYarn];
151 SurfaceMesh.RemoveUnreferencedNodes();
152
153 // Get the yarn surface
154 int i, ElementNum;
155 list<int>::iterator itIndex;
156
157 pair<int,int> Element;
158 Element.first = iYarn;
159
160
161 list<int> &Indices = SurfaceMesh.GetIndices(CMesh::QUAD);
162 for (itIndex = Indices.begin(), ElementNum = 0; itIndex != Indices.end(); ++ElementNum)
163 {
164 vector<int> ElemIndices;
165
166 for (i=0; i<CMesh::GetNumNodes(CMesh::QUAD); ++i)
167 {
168 ElemIndices.push_back(*itIndex);
169 ++itIndex;
170 }
171
172 XYZ N1 = SurfaceMesh.GetNode(ElemIndices[0]);
173 XYZ N2 = SurfaceMesh.GetNode(ElemIndices[1]);
174 XYZ N3 = SurfaceMesh.GetNode(ElemIndices[2]);
175 XYZ Normal = CrossProduct(N2-N1, N3-N1);
176
177 // Filter out all the elements based on their normal
178
179 Element.second = ElementNum;
180 if ( Normal.z > 0 ) // Upper surface
181 {
182 UpperFaces.push_back(Element);
183 }
184 else // Lower surface
185 {
186 LowerFaces.push_back(Element);
187 }
188
189 }
190
191
192}
193
194void CShellElementExport::GetYarnSurface(int iYarn, vector<pair<int,int>> &Elements )
195{
196 // Get the yarn surface
197 int ElementNum;
198
199 pair<int,int> Element;
200 Element.first = iYarn;
201
202
203 list<int> &Indices = m_YarnMeshes[iYarn].GetIndices(CMesh::QUAD);
204 int numElements = m_YarnMeshes[iYarn].GetNumElements(CMesh::QUAD);
205 for ( ElementNum = 0; ElementNum < numElements ; ++ElementNum )
206 {
207 Element.second = ElementNum;
208 Elements.push_back(Element);
209 }
210
211}
212
213void CShellElementExport::CreateSurfaces(ostream &Output, map< string, vector<pair<YarnNumber,int>> > &SurfaceDefinitions)
214{
215 // Now output the surface definitions
216 Output << "***************************" << endl;
217 Output << "*** SURFACE DEFINITIONS ***" << endl;
218 Output << "***************************" << endl;
219 vector<pair<YarnNumber,int>>::iterator itElements;
220
221 map<string, vector<pair<YarnNumber,int>> >::iterator itSurfDef;
222
223 for (itSurfDef = SurfaceDefinitions.begin(); itSurfDef != SurfaceDefinitions.end(); ++itSurfDef)
224 {
225 Output << "*Surface, Name=" << itSurfDef->first << ", Type=Element" << endl;
226 for (itElements = itSurfDef->second.begin(); itElements != itSurfDef->second.end(); ++itElements)
227 {
228 // ABAQUS is 1 based, so add 1
229 Output << GetGlobalElementIndex(*itElements)+1 << endl;
230 }
231 }
232}
233
234
235int CShellElementExport::GetGlobalElementIndex(pair<YarnNumber,int> Element)
236{
237 return m_ElementIndexOffsets[Element.first] + Element.second; // m_ElementOffsets[Yarn] + ElementIndex;
238}
239
241{
242 TGLOG("Getting point information");
243 vector<POINT_INFO> YarnElementInfo;
244 for ( int i = 0; i < Textile.GetNumYarns(); ++i )
245 {
246 if (!m_YarnMeshes[i].GetIndices(CMesh::QUAD).empty() )
247 {
248 YarnElementInfo.clear();
249 Textile.GetPointInformation( m_YarnMeshes[i].GetElementCenters( (CMesh::QUAD) ), YarnElementInfo, i, 0.005, true );
250 m_ElementInfo.insert( m_ElementInfo.end(), YarnElementInfo.begin(), YarnElementInfo.end() );
251 }
252 }
253}
254
256{
257 // Where yarn meshes are combined to create ABAQUS file
258 // need to create offsets for node and element numbering
259 int i, iNumYarns = (int)m_YarnMeshes.size();
260
261 int iElemIndexOffset = 0;
262 m_ElementIndexOffsets.clear();
263
264 for (i=0; i<iNumYarns; ++i)
265 {
266 m_ElementIndexOffsets[i] = iElemIndexOffset;
267 iElemIndexOffset += m_YarnMeshes[i].GetNumElements(CMesh::QUAD);
268 }
269
270 m_NodeIndexOffsets.clear();
271 int iNodeIndexOffset = 0;
272 for (i=0; i<iNumYarns; ++i)
273 {
274 m_NodeIndexOffsets[i] = iNodeIndexOffset;
275 iNodeIndexOffset += m_YarnMeshes[i].GetNumNodes();
276 }
277}
278
279void CShellElementExport::CreateContacts(ostream &Output, const CTextile &Textile)
280{
281 Output << "***************************" << endl;
282 Output << "*** CONTACT DEFINITIONS ***" << endl;
283 Output << "***************************" << endl;
284
285 const CTextileWeave* pWeave = dynamic_cast<const CTextileWeave*>(&Textile);
286 const CTextile3DWeave* p3DWeave = dynamic_cast<const CTextile3DWeave*>(&Textile);
287 if (pWeave)
288 {
289 CreateContacts(Output, *pWeave);
290 }
291 else if (p3DWeave)
292 {
293 Output << "*** WARNING: Contacts are only created for upper and lower surfaces." << endl;
294 Output << "*** Any contacts between binder yarns and sides of warp and weft" << endl;
295 Output << "*** yarns must be specified manually" << endl;
296 CreateContacts(Output, *p3DWeave);
297 }
298 else
299 {
300 Output << "*** WARNING: TexGen was unable to create contact definitions automatically" << endl;
301 Output << "*** because the textile is not of type CTextileWeave" << endl;
302 }
303
304}
305
306void CShellElementExport::CreateContacts(ostream &Output, const CTextileWeave &Weave)
307{
308 set<pair<int, int> > Contacts;
309 int i, j, k;
310 for (i=0; i<Weave.GetNumYYarns(); ++i)
311 {
312 for (j=0; j<Weave.GetNumXYarns(); ++j)
313 {
314 const vector<PATTERN2D> &Cell = Weave.GetCell(i, j);
315 for (k=1; k<(int)Cell.size(); ++k)
316 {
317 Contacts.insert(make_pair(Weave.GetYarnIndex(i, j, k-1), Weave.GetYarnIndex(i, j, k)));
318 }
319 }
320 }
321 OutputContacts( Output, Contacts );
322}
323
324void CShellElementExport::CreateContacts(ostream &Output, const CTextile3DWeave &Weave)
325{
326 set<pair<int, int> > Contacts;
327 int i, j, k;
328 for (i=0; i<Weave.GetNumYYarns(); ++i)
329 {
330 for (j=0; j<Weave.GetNumXYarns(); ++j)
331 {
332 const vector<PATTERN3D> &Cell = Weave.GetCell(i, j);
333 for (k=1; k<(int)Cell.size(); ++k)
334 {
335 if ( Cell[k-1] != PATTERN3D_NOYARN && Cell[k] != PATTERN3D_NOYARN )
336 Contacts.insert(make_pair(Weave.GetYarnIndex(i, j, k-1), Weave.GetYarnIndex(i, j, k)));
337 }
338 }
339 }
340 OutputContacts( Output, Contacts );
341}
342
343void CShellElementExport::OutputContacts( ostream &Output, set<pair<int, int> > &Contacts )
344{
345 set<pair<int, int> >::iterator itContact;
346 for (itContact = Contacts.begin(); itContact != Contacts.end(); ++itContact)
347 {
348 if ( m_bWholeSurfaces )
349 CreateContact(Output, "YarnSurf" + stringify(itContact->first),
350 "YarnSurf" + stringify(itContact->second) , "Yarn");
351 else
352 CreateContact(Output, "Yarn" + stringify(itContact->first) + "Upper",
353 "Yarn" + stringify(itContact->second) + "Lower", "Yarn");
354 }
355}
356
357void CShellElementExport::CreateContact(ostream &Output, string Name1, string Name2, string InteractionName)
358{
359 Output << "*Contact Pair, Interaction=" << InteractionName << endl;
360 Output << Name1 << ", " << Name2 << endl;
361}
362
364{
365 Output << "************" << endl;
366 Output << "*** INTERACTION PROPERTIES ***" << endl;
367 Output << "************" << endl;
368 Output << "*Surface Interaction, name=YARN" << endl;
369 Output << "*Friction" << endl;
370 Output << "0.112," << endl;
371 Output << "*Surface Behavior, pressure-overclosure=HARD" << endl;
372}
#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
Abstract base class representing the domain in which a textile cell may lie.
Definition: Domain.h:34
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
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
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
@ POLYGON
Definition: Mesh.h:76
void CreateSurfaceDefinitions(int iNumYarns, const vector< XYZ > &Repeats, map< string, vector< pair< int, int > > > &SurfaceDefinitions)
void OutputContacts(ostream &Output, set< pair< int, int > > &Contacts)
void GetElementInfo(CTextile &Textile)
Get the element info for centre points of surface mesh elements.
void BuildIndexOffsets()
Generate node and element offsets for merging individual yarn nodes and elements into one ABAQUS file...
void CreateInteractions(ostream &Output)
void GetYarnSurfaces(int iYarn, const vector< XYZ > &Repeats, vector< pair< int, int > > &UpperFaces, vector< pair< int, int > > &LowerFaces)
void CreateSurfaces(ostream &Output, map< string, vector< pair< YarnNumber, int > > > &SurfaceDefinitions)
void CreateContact(ostream &Output, string Name1, string Name2, string InteractionName)
int GetGlobalElementIndex(pair< YarnNumber, int > Element)
void CreateContacts(ostream &Output, const CTextile &Textile)
map< YarnNumber, int > m_NodeIndexOffsets
CTextileMaterials * m_Materials
Class for export of material properties.
bool m_bTrimSurface
True if surfaces to be trimmed to domain.
map< YarnNumber, int > m_ElementIndexOffsets
bool SaveShellElementToABAQUS(string Filename, CTextile &Textile)
Save surface mesh to ABAQUS input file.
void GetYarnSurface(int iYarn, vector< pair< int, int > > &Elements)
vector< POINT_INFO > m_ElementInfo
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 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
void OutputMaterials(ostream &Output, int iNumYarns, bool bMatrixOnly)
Output materials and assign to yarn element sets.
Definition: Materials.cpp:187
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
bool AddSurfaceToMesh(CMesh &Mesh, bool bAddEndCaps=true) const
Create surface mesh for this yarn and add it to the surface mesh object.
Definition: Yarn.cpp:860
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 ReplaceFilenameSpaces(std::string Filename)
Replaces spaces in filename with underscore.
Definition: Misc.cpp:130
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
@ PATTERN3D_NOYARN
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