1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011-2011 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "codedFixedValueFvPatchField.H"
27 #include "addToRunTimeSelectionTable.H"
28 #include "fvPatchFieldMapper.H"
29 #include "surfaceFields.H"
30 #include "volFields.H"
31 #include "dlLibraryTable.H"
34 #include "SHA1Digest.H"
35 #include "dynamicCode.H"
36 #include "dynamicCodeContext.H"
37 #include "stringOps.H"
38 #include "IOdictionary.H"
43 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
46 const Foam::word Foam::codedFixedValueFvPatchField<Type>::codeTemplateC
47 = "fixedValueFvPatchFieldTemplate.C";
50 const Foam::word Foam::codedFixedValueFvPatchField<Type>::codeTemplateH
51 = "fixedValueFvPatchFieldTemplate.H";
54 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
57 void* Foam::codedFixedValueFvPatchField<Type>::loadLibrary
59 const fileName& libPath,
60 const string& globalFuncName,
61 const dictionary& contextDict
66 // avoid compilation by loading an existing library
69 dlLibraryTable& libs = const_cast<Time&>(this->db().time()).libs();
71 if (libs.open(libPath, false))
73 lib = libs.findLibrary(libPath);
75 // verify the loaded version and unload if needed
78 // provision for manual execution of code after loading
79 if (dlSymFound(lib, globalFuncName))
81 loaderFunctionType function =
82 reinterpret_cast<loaderFunctionType>
84 dlSym(lib, globalFuncName)
89 (*function)(true); // force load
95 "codedFixedValueFvPatchField<Type>::"
98 ) << "Failed looking up symbol " << globalFuncName
99 << nl << "from " << libPath << exit(FatalIOError);
106 "codedFixedValueFvPatchField<Type>::loadLibrary()",
108 ) << "Failed looking up symbol " << globalFuncName << nl
109 << "from " << libPath << exit(FatalIOError);
112 if (!libs.close(libPath, false))
116 "codedFixedValueFvPatchField<Type>::loadLibrary()",
118 ) << "Failed unloading library "
120 << exit(FatalIOError);
132 void Foam::codedFixedValueFvPatchField<Type>::unloadLibrary
134 const fileName& libPath,
135 const string& globalFuncName,
136 const dictionary& contextDict
146 dlLibraryTable& libs = const_cast<Time&>(this->db().time()).libs();
148 lib = libs.findLibrary(libPath);
155 // provision for manual execution of code before unloading
156 if (dlSymFound(lib, globalFuncName))
158 loaderFunctionType function =
159 reinterpret_cast<loaderFunctionType>
161 dlSym(lib, globalFuncName)
166 (*function)(false); // force unload
172 "codedFixedValueFvPatchField<Type>::unloadLibrary()",
174 ) << "Failed looking up symbol " << globalFuncName << nl
175 << "from " << libPath << exit(FatalIOError);
179 if (!libs.close(libPath, false))
183 "codedFixedValueFvPatchField<Type>::"
186 ) << "Failed unloading library " << libPath
187 << exit(FatalIOError);
193 void Foam::codedFixedValueFvPatchField<Type>::setFieldTemplates
198 word fieldType(pTraits<Type>::typeName);
200 // template type for fvPatchField
201 dynCode.setFilterVariable("TemplateType", fieldType);
203 // Name for fvPatchField - eg, ScalarField, VectorField, ...
204 fieldType[0] = toupper(fieldType[0]);
205 dynCode.setFilterVariable("FieldType", fieldType + "Field");
209 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
212 const Foam::IOdictionary& Foam::codedFixedValueFvPatchField<Type>::dict() const
214 const objectRegistry& obr = this->db();
216 if (obr.foundObject<IOdictionary>("codeDict"))
218 return obr.lookupObject<IOdictionary>("codeDict");
229 this->db().time().system(),
231 IOobject::MUST_READ_IF_MODIFIED,
241 void Foam::codedFixedValueFvPatchField<Type>::createLibrary
243 dynamicCode& dynCode,
244 const dynamicCodeContext& context
247 bool create = Pstream::master();
251 // Write files for new library
252 if (!dynCode.upToDate(context))
254 // filter with this context
255 dynCode.reset(context);
257 // take no chances - typeName must be identical to redirectType_
258 dynCode.setFilterVariable("typeName", redirectType_);
260 // set TemplateType and FieldType filter variables
261 // (for fvPatchField)
262 setFieldTemplates(dynCode);
264 // compile filtered C template
265 dynCode.addCompileFile(codeTemplateC);
267 // copy filtered H template
268 dynCode.addCopyFile(codeTemplateH);
271 // debugging: make BC verbose
272 // dynCode.setFilterVariable("verbose", "true");
273 // Info<<"compile " << redirectType_ << " sha1: "
274 // << context.sha1() << endl;
276 // define Make/options
277 dynCode.setMakeOptions
280 "-I$(LIB_SRC)/finiteVolume/lnInclude \\\n"
282 + "\n\nLIB_LIBS = \\\n"
284 + " -lfiniteVolume \\\n"
288 if (!dynCode.copyOrCreateFiles(true))
292 "codedFixedValueFvPatchField<Type>::createLibrary(..)",
294 ) << "Failed writing files for" << nl
295 << dynCode.libRelPath() << nl
296 << exit(FatalIOError);
300 if (!dynCode.wmakeLibso())
304 "codedFixedValueFvPatchField<Type>::createLibrary(..)",
306 ) << "Failed wmake " << dynCode.libRelPath() << nl
307 << exit(FatalIOError);
312 // all processes must wait for compile to finish
313 reduce(create, orOp<bool>());
318 void Foam::codedFixedValueFvPatchField<Type>::updateLibrary() const
320 dynamicCode::checkSecurity
322 "codedFixedValueFvPatchField<Type>::updateLibrary()",
326 // use system/codeDict or in-line
327 const dictionary& codeDict =
331 : this->dict().subDict(redirectType_)
334 dynamicCodeContext context(codeDict);
336 // codeName: redirectType + _<sha1>
337 // codeDir : redirectType
340 redirectType_ + context.sha1().str(true),
343 const fileName libPath = dynCode.libPath();
346 // the correct library was already loaded => we are done
347 if (const_cast<Time&>(this->db().time()).libs().findLibrary(libPath))
352 Info<< "Using dynamicCode for patch " << this->patch().name()
353 << " on field " << this->dimensionedInternalField().name() << nl
354 << "at line " << codeDict.startLineNumber()
355 << " in " << codeDict.name() << endl;
358 // remove instantiation of fvPatchField provided by library
359 redirectPatchFieldPtr_.clear();
361 // may need to unload old library
365 dynamicCode::libraryBaseName(oldLibPath_),
369 // try loading an existing library (avoid compilation when possible)
370 if (!loadLibrary(libPath, dynCode.codeName(), context.dict()))
372 createLibrary(dynCode, context);
374 loadLibrary(libPath, dynCode.codeName(), context.dict());
377 // retain for future reference
378 oldLibPath_ = libPath;
382 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
385 Foam::codedFixedValueFvPatchField<Type>::codedFixedValueFvPatchField
388 const DimensionedField<Type, volMesh>& iF
391 fixedValueFvPatchField<Type>(p, iF),
393 redirectPatchFieldPtr_()
398 Foam::codedFixedValueFvPatchField<Type>::codedFixedValueFvPatchField
400 const codedFixedValueFvPatchField<Type>& ptf,
402 const DimensionedField<Type, volMesh>& iF,
403 const fvPatchFieldMapper& mapper
406 fixedValueFvPatchField<Type>(ptf, p, iF, mapper),
408 redirectType_(ptf.redirectType_),
409 oldLibPath_(ptf.oldLibPath_),
410 redirectPatchFieldPtr_()
415 Foam::codedFixedValueFvPatchField<Type>::codedFixedValueFvPatchField
418 const DimensionedField<Type, volMesh>& iF,
419 const dictionary& dict
422 fixedValueFvPatchField<Type>(p, iF, dict),
424 redirectType_(dict.lookup("redirectType")),
426 redirectPatchFieldPtr_()
433 Foam::codedFixedValueFvPatchField<Type>::codedFixedValueFvPatchField
435 const codedFixedValueFvPatchField<Type>& ptf
438 fixedValueFvPatchField<Type>(ptf),
440 redirectType_(ptf.redirectType_),
441 oldLibPath_(ptf.oldLibPath_),
442 redirectPatchFieldPtr_()
447 Foam::codedFixedValueFvPatchField<Type>::codedFixedValueFvPatchField
449 const codedFixedValueFvPatchField<Type>& ptf,
450 const DimensionedField<Type, volMesh>& iF
453 fixedValueFvPatchField<Type>(ptf, iF),
455 redirectType_(ptf.redirectType_),
456 oldLibPath_(ptf.oldLibPath_),
457 redirectPatchFieldPtr_()
461 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
464 const Foam::fvPatchField<Type>&
465 Foam::codedFixedValueFvPatchField<Type>::redirectPatchField() const
467 if (!redirectPatchFieldPtr_.valid())
470 // Make sure to construct the patchfield with up-to-date value
473 os.writeKeyword("type") << redirectType_ << token::END_STATEMENT
475 static_cast<const Field<Type>&>(*this).writeEntry("value", os);
476 IStringStream is(os.str());
479 redirectPatchFieldPtr_.set
481 fvPatchField<Type>::New
484 this->dimensionedInternalField(),
489 return redirectPatchFieldPtr_();
494 void Foam::codedFixedValueFvPatchField<Type>::updateCoeffs()
501 // Make sure library containing user-defined fvPatchField is up-to-date
504 const fvPatchField<Type>& fvp = redirectPatchField();
506 const_cast<fvPatchField<Type>&>(fvp).updateCoeffs();
508 // Copy through value
509 this->operator==(fvp);
511 fixedValueFvPatchField<Type>::updateCoeffs();
516 void Foam::codedFixedValueFvPatchField<Type>::evaluate
518 const Pstream::commsTypes commsType
521 // Make sure library containing user-defined fvPatchField is up-to-date
524 const fvPatchField<Type>& fvp = redirectPatchField();
526 const_cast<fvPatchField<Type>&>(fvp).evaluate(commsType);
528 fixedValueFvPatchField<Type>::evaluate(commsType);
533 void Foam::codedFixedValueFvPatchField<Type>::write(Ostream& os) const
535 fixedValueFvPatchField<Type>::write(os);
536 os.writeKeyword("redirectType") << redirectType_
537 << token::END_STATEMENT << nl;
539 if (dict_.found("code"))
541 os.writeKeyword("code")
542 << token::HASH << token::BEGIN_BLOCK;
544 os.writeQuoted(string(dict_["code"]), false)
545 << token::HASH << token::END_BLOCK
546 << token::END_STATEMENT << nl;
551 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
554 // ************************************************************************* //