abaqusSurfaceWriterImpl.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2020-2022 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "IOmanip.H"
29 #include "OFstream.H"
30 #include "OSspecific.H"
31 
32 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
33 
34 template<class Type>
35 Foam::Ostream& Foam::surfaceWriters::abaqusWriter::writeFaceValue
36 (
37  Ostream& os,
38  const Type& value,
39  const label elemId
40 ) const
41 {
43  {
44  const label solidId =
46 
47  const label sideNum =
49 
50  // Element-id: 0-based to 1-based
51  // Side-id: always 1-based
52  os << (solidId + 1) << ", P" << sideNum;
53  }
54  else
55  {
56  // Element-id: 0-based to 1-based
57  os << (elemId + 1) << ", P";
58  }
59 
60  os << ", ";
62  {
63  os << value;
64  }
65  else
66  {
67  os << mag(value);
68  }
69  os << nl;
70 
71  return os;
72 }
73 
74 
75 template<class Type>
76 Foam::fileName Foam::surfaceWriters::abaqusWriter::writeTemplate
77 (
78  const word& fieldName,
79  const Field<Type>& localValues
80 )
81 {
82  checkOpen();
83 
84  // Field:
85  // 1) rootdir/<TIME>/<field>_surfaceName.inp
86  // 2) rootdir/<field>/surfaceName_<TIME>.inp
87 
88  fileName outputFile;
89 
90  switch (outputLayout_)
91  {
92  case outputLayoutType::BY_TIME:
93  {
94  outputFile = outputPath_;
95  if (useTimeDir() && !timeName().empty())
96  {
97  // Splice in time-directory
98  outputFile =
99  outputPath_.path() / timeName() / outputPath_.name();
100  }
101 
102  // Append <field>_surfaceName
103  outputFile /= fieldName + '_' + outputPath_.name();
104  break;
105  }
106  case outputLayoutType::BY_FIELD:
107  {
108  outputFile = outputPath_ / fieldName / outputPath_.name();
109  if (!timeName().empty())
110  {
111  // Append time information to file name
112  outputFile += '_' + timeName();
113  }
114  break;
115  }
116  }
117  outputFile.ext("inp");
118 
119 
120  // Implicit geometry merge()
121  tmp<Field<Type>> tfield = adjustField(fieldName, mergeField(localValues));
122 
123  if (verbose_)
124  {
125  Info<< " to " << outputFile << endl;
126  }
127 
128 
129  // const meshedSurf& surf = surface();
130  const meshedSurfRef& surf = adjustSurface();
131 
132  if (UPstream::master() || !parallel_)
133  {
134  const auto& values = tfield();
135 
136  if (!isDir(outputFile.path()))
137  {
138  mkDir(outputFile.path());
139  }
140 
141  // const scalar timeValue(0);
142 
143 
144  // Additional bookkeeping for decomposing non tri/quad
145  labelList decompOffsets;
146  DynamicList<face> decompFaces;
147 
148 
149  OFstream os(outputFile);
150 
151  if (noGeometry_ || wroteGeom_)
152  {
153  // Geometry already written (or suppressed)
154  // - still need decomposition information
155 
157  (
158  surf.points(),
159  surf.faces(),
160  decompOffsets,
161  decompFaces
162  );
163  }
164  else
165  {
166  // Write geometry (separate file)
167 
168  OFstream osGeom(outputFile.lessExt().ext("abq"));
169  writeGeometry(osGeom, surf, decompOffsets, decompFaces);
170  }
171 
172  // Write field
173  // *DLOAD
174  // Element-based: // elemId, P, 1000
175  // Surface-based: // elemId, P4, 1000
176 
177  os << "**" << nl
178  << "** field = " << fieldName << nl
179  << "** type = " << pTraits<Type>::typeName << nl;
180 
181  if (useTimeDir() && !timeName().empty())
182  {
183  os << "** time = " << timeName() << nl;
184  }
185 
186  os << "**" << nl
187  << "*DLOAD" << nl;
188 
189 
190  // Regular (undecomposed) faces
191  const faceList& faces = surf.faces();
192  const labelList& elemIds = surf.faceIds();
193 
194  // Possible to use faceIds?
195  const bool useOrigFaceIds =
196  (
197  elemIds.size() == faces.size()
198  && decompFaces.empty()
199  );
200 
201 
202  label elemId = 0;
203 
204  if (this->isPointData())
205  {
206  forAll(faces, facei)
207  {
208  if (useOrigFaceIds)
209  {
210  // When available and not decomposed
211  elemId = elemIds[facei];
212  }
213 
214  const label beginElemId = elemId;
215 
216  // Any face decomposition
217  for
218  (
219  label decompi = decompOffsets[facei];
220  decompi < decompOffsets[facei+1];
221  ++decompi
222  )
223  {
224  const face& f = decompFaces[decompi];
225 
226  Type v = Zero;
227  for (const label verti : f)
228  {
229  v += values[verti];
230  }
231  v /= f.size();
232 
233  writeFaceValue(os, v, elemId); // 0-based
234  ++elemId;
235  }
236 
237 
238  // Face not decomposed
239  if (beginElemId == elemId)
240  {
241  const face& f = faces[facei];
242 
243  Type v = Zero;
244  for (const label verti : f)
245  {
246  v += values[verti];
247  }
248  v /= f.size();
249 
250  writeFaceValue(os, v, elemId); // 0-based
251  ++elemId;
252  }
253  }
254  }
255  else
256  {
257  auto valIter = values.cbegin();
258 
259  forAll(faces, facei)
260  {
261  if (useOrigFaceIds)
262  {
263  // When available and not decomposed
264  elemId = elemIds[facei];
265  }
266 
267  const Type v(*valIter);
268  ++valIter;
269 
270  label nValues =
271  max
272  (
273  label(1),
274  (decompOffsets[facei+1] - decompOffsets[facei])
275  );
276 
277  while (nValues--)
278  {
279  writeFaceValue(os, v, elemId); // 0-based
280  ++elemId;
281  }
282  }
283  }
284 
285  os << "**" << nl
286  << "**" << nl;
287  }
288 
289  wroteGeom_ = true;
290  return outputFile;
291 }
292 
293 
294 // ************************************************************************* //
static label decodeSolidSideNum(const label combinedId)
Entangle solid side id from synthetic face Id Synthesize faceId from solid element Id and sideId...
Definition: ABAQUSCore.H:335
A class for handling file names.
Definition: fileName.H:72
writer writeGeometry()
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
A traits class, which is primarily used for primitives and vector-space.
Definition: pTraits.H:75
static std::string path(const std::string &str)
Return directory path name (part before last /)
Definition: fileNameI.H:169
word ext() const
Return file name extension (part after last .)
Definition: fileNameI.H:211
static label decodeSolidElementId(const label combinedId)
Entangle solid element id from synthetic face Id.
Definition: ABAQUSCore.H:321
static bool isEncodedSolidId(const label combinedId)
Is a combined (synthetic) face Id?
Definition: ABAQUSCore.H:305
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
bool isDir(const fileName &name, const bool followLink=true)
Does the name exist as a DIRECTORY in the file system?
Definition: POSIX.C:860
List< face > faceList
List of faces.
Definition: faceListFwd.H:39
List< T > values(const HashTable< T, Key, Hash > &tbl, const bool doSort=false)
List of values from HashTable, optionally sorted.
Definition: HashOps.H:164
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
word timeName
Definition: getTimeIndex.H:3
bool mkDir(const fileName &pathName, mode_t mode=0777)
Make a directory and return an error if it could not be created.
Definition: POSIX.C:614
Generic templated field type.
Definition: Field.H:62
A class for handling words, derived from Foam::string.
Definition: word.H:63
static label faceDecomposition(const UList< point > &points, const UList< face > &faces, labelList &decompOffsets, DynamicList< face > &decompFaces)
Calculate face decomposition for non tri/quad faces.
Definition: ABAQUSCore.C:817
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:56
Istream and Ostream manipulators taking arguments.
OBJstream os(runTime.globalPath()/outputName)
labelList f(nPoints)
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition: UPstream.H:1082
fileName lessExt() const
Return file name without extension (part before last .)
Definition: fileNameI.H:238
messageStream Info
Information stream (stdout output on master, null elsewhere)
List< label > labelList
A List of labels.
Definition: List.H:62
A class for managing temporary objects.
Definition: HashPtrTable.H:50
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127