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 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 "OFstream.H"
29 #include "IOmanip.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 {
42  if (fileFormats::ABAQUSCore::isEncodedSolidId(elemId))
43  {
44  const label solidId =
45  fileFormats::ABAQUSCore::decodeSolidElementId(elemId);
46 
47  const label sideNum =
48  fileFormats::ABAQUSCore::decodeSolidSideNum(elemId);
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  // Output scaling for the variable, but not for integer types.
121  // could also solve with clever templating
122 
123  const scalar varScale =
124  (
125  std::is_integral<Type>::value
126  ? scalar(1)
127  : fieldScale_.getOrDefault<scalar>(fieldName, 1)
128  );
129 
130  if (verbose_)
131  {
132  Info<< "Writing field " << fieldName;
133  if (!equal(varScale, 1))
134  {
135  Info<< " (scaling " << varScale << ')';
136  }
137  Info<< " to " << outputFile << endl;
138  }
139 
140 
141  // Implicit geometry merge()
142  tmp<Field<Type>> tfield = mergeField(localValues) * varScale;
143 
144  const meshedSurf& surf = surface();
145 
146  if (Pstream::master() || !parallel_)
147  {
148  const auto& values = tfield();
149 
150  if (!isDir(outputFile.path()))
151  {
152  mkDir(outputFile.path());
153  }
154 
155  // const scalar timeValue(0);
156 
157 
158  // Additional bookkeeping for decomposing non tri/quad
159  labelList decompOffsets;
160  DynamicList<face> decompFaces;
161 
162 
163  OFstream os(outputFile);
164 
165  if (noGeometry_ || wroteGeom_)
166  {
167  // Geometry already written (or suppressed)
168  // - still need decomposition information
169 
170  fileFormats::ABAQUSCore::faceDecomposition
171  (
172  surf.points(),
173  surf.faces(),
174  decompOffsets,
175  decompFaces
176  );
177  }
178  else
179  {
180  // Write geometry (separate file)
181 
182  OFstream osGeom(outputFile.lessExt().ext("abq"));
183  writeGeometry(osGeom, surf, decompOffsets, decompFaces);
184  }
185 
186  // Write field
187  // *DLOAD
188  // Element-based: // elemId, P, 1000
189  // Surface-based: // elemId, P4, 1000
190 
191  os << "**" << nl
192  << "** field = " << fieldName << nl
193  << "** type = " << pTraits<Type>::typeName << nl;
194 
195  if (useTimeDir() && !timeName().empty())
196  {
197  os << "** time = " << timeName() << nl;
198  }
199 
200  os << "**" << nl
201  << "*DLOAD" << nl;
202 
203 
204  // Regular (undecomposed) faces
205  const faceList& faces = surf.faces();
206  const labelList& elemIds = surf.faceIds();
207 
208  // Possible to use faceIds?
209  const bool useOrigFaceIds =
210  (
211  elemIds.size() == faces.size()
212  && decompFaces.empty()
213  );
214 
215 
216  label elemId = 0;
217 
218  if (this->isPointData())
219  {
220  forAll(faces, facei)
221  {
222  if (useOrigFaceIds)
223  {
224  // When available and not decomposed
225  elemId = elemIds[facei];
226  }
227 
228  const label beginElemId = elemId;
229 
230  // Any face decomposition
231  for
232  (
233  label decompi = decompOffsets[facei];
234  decompi < decompOffsets[facei+1];
235  ++decompi
236  )
237  {
238  const face& f = decompFaces[decompi];
239 
240  Type v = Zero;
241  for (const label verti : f)
242  {
243  v += values[verti];
244  }
245  v /= f.size();
246 
247  writeFaceValue(os, v, elemId); // 0-based
248  ++elemId;
249  }
250 
251 
252  // Face not decomposed
253  if (beginElemId == elemId)
254  {
255  const face& f = faces[facei];
256 
257  Type v = Zero;
258  for (const label verti : f)
259  {
260  v += values[verti];
261  }
262  v /= f.size();
263 
264  writeFaceValue(os, v, elemId); // 0-based
265  ++elemId;
266  }
267  }
268  }
269  else
270  {
271  auto valIter = values.cbegin();
272 
273  forAll(faces, facei)
274  {
275  if (useOrigFaceIds)
276  {
277  // When available and not decomposed
278  elemId = elemIds[facei];
279  }
280 
281  const Type v(*valIter);
282  ++valIter;
283 
284  label nValues =
285  max
286  (
287  label(1),
288  (decompOffsets[facei+1] - decompOffsets[facei])
289  );
290 
291  while (nValues--)
292  {
293  writeFaceValue(os, v, elemId); // 0-based
294  ++elemId;
295  }
296  }
297  }
298 
299  os << "**" << nl
300  << "**" << nl;
301  }
302 
303  wroteGeom_ = true;
304  return outputFile;
305 }
306 
307 
308 // ************************************************************************* //
OSspecific.H
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::fileName
A class for handling file names.
Definition: fileName.H:73
Foam::fileName::path
static std::string path(const std::string &str)
Return directory path name (part before last /)
Definition: fileNameI.H:176
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:61
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::DynamicList
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:55
Foam::HashTableOps::values
List< T > values(const HashTable< T, Key, Hash > &tbl, const bool doSort=false)
List of values from HashTable, optionally sorted.
Definition: HashOps.H:149
Foam::meshedSurf::faces
virtual const faceList & faces() const =0
The faces used for the surface.
Foam::meshedSurf
Abstract definition of a meshed surface defined by faces and points.
Definition: meshedSurf.H:49
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::fileName::lessExt
fileName lessExt() const
Return file name without extension (part before last .)
Definition: fileNameI.H:230
Foam::MatrixTools::equal
bool equal(const Matrix< Form1, Type > &A, const Matrix< Form2, Type > &B, const bool verbose=false, const label maxDiffs=10, const scalar relTol=1e-5, const scalar absTol=1e-8)
Compare matrix elements for absolute or relative equality.
Definition: MatrixTools.C:34
writeGeometry
writer writeGeometry()
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
OFstream.H
Foam::Field
Generic templated field type.
Definition: Field.H:63
Foam::Info
messageStream Info
Information stream (stdout output on master, null elsewhere)
IOmanip.H
Istream and Ostream manipulators taking arguments.
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
Foam::meshedSurf::points
virtual const pointField & points() const =0
The points used for the surface.
timeName
word timeName
Definition: getTimeIndex.H:3
os
OBJstream os(runTime.globalPath()/outputName)
Foam::fileName::ext
word ext() const
Return file name extension (part after last .)
Definition: fileNameI.H:218
Foam::OFstream
Output to file stream, using an OSstream.
Definition: OFstream.H:53
Foam::meshedSurf::faceIds
virtual const labelList & faceIds() const
Per-face identifier (eg, element Id)
Definition: meshedSurf.H:83
Foam::nl
constexpr char nl
Definition: Ostream.H:404
f
labelList f(nPoints)
Foam::List< label >
Foam::pTraits
A traits class, which is primarily used for primitives.
Definition: pTraits.H:56
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:72
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
Foam::mkDir
bool mkDir(const fileName &pathName, mode_t mode=0777)
Make a directory and return an error if it could not be created.
Definition: MSwindows.C:507
Foam::isDir
bool isDir(const fileName &name, const bool followLink=true)
Does the name exist as a DIRECTORY in the file system?
Definition: MSwindows.C:643