Initial commit for version 2.0.x patch release
[OpenFOAM-2.0.x.git] / src / finiteVolume / fields / fvPatchFields / derived / codedFixedValue / codedFixedValueFvPatchField.C
blob6d268371b615fd6fac560ab36dddce2e8537723e
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 2011-2011 OpenCFD Ltd.
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
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
19     for more details.
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"
32 #include "IFstream.H"
33 #include "OFstream.H"
34 #include "SHA1Digest.H"
35 #include "dynamicCode.H"
36 #include "dynamicCodeContext.H"
37 #include "stringOps.H"
38 #include "IOdictionary.H"
40 #include <dlfcn.h>
41 #include <link.h>
43 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
45 template<class Type>
46 const Foam::word Foam::codedFixedValueFvPatchField<Type>::codeTemplateC
47     = "fixedValueFvPatchFieldTemplate.C";
49 template<class Type>
50 const Foam::word Foam::codedFixedValueFvPatchField<Type>::codeTemplateH
51     = "fixedValueFvPatchFieldTemplate.H";
54 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
56 template<class Type>
57 void* Foam::codedFixedValueFvPatchField<Type>::loadLibrary
59     const fileName& libPath,
60     const string& globalFuncName,
61     const dictionary& contextDict
62 ) const
64     void* lib = 0;
66     // avoid compilation by loading an existing library
67     if (!libPath.empty())
68     {
69         dlLibraryTable& libs = const_cast<Time&>(this->db().time()).libs();
71         if (libs.open(libPath, false))
72         {
73             lib = libs.findLibrary(libPath);
75             // verify the loaded version and unload if needed
76             if (lib)
77             {
78                 // provision for manual execution of code after loading
79                 if (dlSymFound(lib, globalFuncName))
80                 {
81                     loaderFunctionType function =
82                         reinterpret_cast<loaderFunctionType>
83                         (
84                             dlSym(lib, globalFuncName)
85                         );
87                     if (function)
88                     {
89                         (*function)(true);    // force load
90                     }
91                     else
92                     {
93                         FatalIOErrorIn
94                         (
95                             "codedFixedValueFvPatchField<Type>::"
96                             "updateLibrary()",
97                             contextDict
98                         )   << "Failed looking up symbol " << globalFuncName
99                             << nl << "from " << libPath << exit(FatalIOError);
100                     }
101                 }
102                 else
103                 {
104                     FatalIOErrorIn
105                     (
106                         "codedFixedValueFvPatchField<Type>::loadLibrary()",
107                         contextDict
108                     )   << "Failed looking up symbol " << globalFuncName << nl
109                         << "from " << libPath << exit(FatalIOError);
111                     lib = 0;
112                     if (!libs.close(libPath, false))
113                     {
114                         FatalIOErrorIn
115                         (
116                             "codedFixedValueFvPatchField<Type>::loadLibrary()",
117                             contextDict
118                         )   << "Failed unloading library "
119                             << libPath
120                             << exit(FatalIOError);
121                     }
122                 }
123             }
124         }
125     }
127     return lib;
131 template<class Type>
132 void Foam::codedFixedValueFvPatchField<Type>::unloadLibrary
134     const fileName& libPath,
135     const string& globalFuncName,
136     const dictionary& contextDict
137 ) const
139     void* lib = 0;
141     if (libPath.empty())
142     {
143         return;
144     }
146     dlLibraryTable& libs = const_cast<Time&>(this->db().time()).libs();
148     lib = libs.findLibrary(libPath);
150     if (!lib)
151     {
152         return;
153     }
155     // provision for manual execution of code before unloading
156     if (dlSymFound(lib, globalFuncName))
157     {
158         loaderFunctionType function =
159             reinterpret_cast<loaderFunctionType>
160             (
161                 dlSym(lib, globalFuncName)
162             );
164         if (function)
165         {
166             (*function)(false);    // force unload
167         }
168         else
169         {
170             FatalIOErrorIn
171             (
172                 "codedFixedValueFvPatchField<Type>::unloadLibrary()",
173                 contextDict
174             )   << "Failed looking up symbol " << globalFuncName << nl
175                 << "from " << libPath << exit(FatalIOError);
176         }
177     }
179     if (!libs.close(libPath, false))
180     {
181         FatalIOErrorIn
182         (
183             "codedFixedValueFvPatchField<Type>::"
184             "updateLibrary()",
185             contextDict
186         )   << "Failed unloading library " << libPath
187             << exit(FatalIOError);
188     }
192 template<class Type>
193 void Foam::codedFixedValueFvPatchField<Type>::setFieldTemplates
195     dynamicCode& dynCode
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  * * * * * * * * * * * //
211 template<class Type>
212 const Foam::IOdictionary& Foam::codedFixedValueFvPatchField<Type>::dict() const
214     const objectRegistry& obr = this->db();
216     if (obr.foundObject<IOdictionary>("codeDict"))
217     {
218         return obr.lookupObject<IOdictionary>("codeDict");
219     }
220     else
221     {
222         return obr.store
223         (
224             new IOdictionary
225             (
226                 IOobject
227                 (
228                     "codeDict",
229                     this->db().time().system(),
230                     this->db(),
231                     IOobject::MUST_READ_IF_MODIFIED,
232                     IOobject::NO_WRITE
233                 )
234             )
235         );
236     }
240 template<class Type>
241 void Foam::codedFixedValueFvPatchField<Type>::createLibrary
243     dynamicCode& dynCode,
244     const dynamicCodeContext& context
245 ) const
247     bool create = Pstream::master();
249     if (create)
250     {
251         // Write files for new library
252         if (!dynCode.upToDate(context))
253         {
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
278             (
279                 "EXE_INC = -g \\\n"
280                 "-I$(LIB_SRC)/finiteVolume/lnInclude \\\n"
281               + context.options()
282               + "\n\nLIB_LIBS = \\\n"
283               + "    -lOpenFOAM \\\n"
284               + "    -lfiniteVolume \\\n"
285               + context.libs()
286             );
288             if (!dynCode.copyOrCreateFiles(true))
289             {
290                 FatalIOErrorIn
291                 (
292                     "codedFixedValueFvPatchField<Type>::createLibrary(..)",
293                     context.dict()
294                 )   << "Failed writing files for" << nl
295                     << dynCode.libRelPath() << nl
296                     << exit(FatalIOError);
297             }
298         }
300         if (!dynCode.wmakeLibso())
301         {
302             FatalIOErrorIn
303             (
304                 "codedFixedValueFvPatchField<Type>::createLibrary(..)",
305                 context.dict()
306             )   << "Failed wmake " << dynCode.libRelPath() << nl
307                 << exit(FatalIOError);
308         }
309     }
312     // all processes must wait for compile to finish
313     reduce(create, orOp<bool>());
317 template<class Type>
318 void Foam::codedFixedValueFvPatchField<Type>::updateLibrary() const
320     dynamicCode::checkSecurity
321     (
322         "codedFixedValueFvPatchField<Type>::updateLibrary()",
323         dict_
324     );
326     // use system/codeDict or in-line
327     const dictionary& codeDict =
328     (
329         dict_.found("code")
330       ? dict_
331       : this->dict().subDict(redirectType_)
332     );
334     dynamicCodeContext context(codeDict);
336     // codeName: redirectType + _<sha1>
337     // codeDir : redirectType
338     dynamicCode dynCode
339     (
340         redirectType_ + context.sha1().str(true),
341         redirectType_
342     );
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))
348     {
349         return;
350     }
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
362     unloadLibrary
363     (
364         oldLibPath_,
365         dynamicCode::libraryBaseName(oldLibPath_),
366         context.dict()
367     );
369     // try loading an existing library (avoid compilation when possible)
370     if (!loadLibrary(libPath, dynCode.codeName(), context.dict()))
371     {
372         createLibrary(dynCode, context);
374         loadLibrary(libPath, dynCode.codeName(), context.dict());
375     }
377     // retain for future reference
378     oldLibPath_ = libPath;
382 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
384 template<class Type>
385 Foam::codedFixedValueFvPatchField<Type>::codedFixedValueFvPatchField
387     const fvPatch& p,
388     const DimensionedField<Type, volMesh>& iF
391     fixedValueFvPatchField<Type>(p, iF),
392     oldLibPath_(),
393     redirectPatchFieldPtr_()
397 template<class Type>
398 Foam::codedFixedValueFvPatchField<Type>::codedFixedValueFvPatchField
400     const codedFixedValueFvPatchField<Type>& ptf,
401     const fvPatch& p,
402     const DimensionedField<Type, volMesh>& iF,
403     const fvPatchFieldMapper& mapper
406     fixedValueFvPatchField<Type>(ptf, p, iF, mapper),
407     dict_(ptf.dict_),
408     redirectType_(ptf.redirectType_),
409     oldLibPath_(ptf.oldLibPath_),
410     redirectPatchFieldPtr_()
414 template<class Type>
415 Foam::codedFixedValueFvPatchField<Type>::codedFixedValueFvPatchField
417     const fvPatch& p,
418     const DimensionedField<Type, volMesh>& iF,
419     const dictionary& dict
422     fixedValueFvPatchField<Type>(p, iF, dict),
423     dict_(dict),
424     redirectType_(dict.lookup("redirectType")),
425     oldLibPath_(),
426     redirectPatchFieldPtr_()
428     updateLibrary();
432 template<class Type>
433 Foam::codedFixedValueFvPatchField<Type>::codedFixedValueFvPatchField
435     const codedFixedValueFvPatchField<Type>& ptf
438     fixedValueFvPatchField<Type>(ptf),
439     dict_(ptf.dict_),
440     redirectType_(ptf.redirectType_),
441     oldLibPath_(ptf.oldLibPath_),
442     redirectPatchFieldPtr_()
446 template<class Type>
447 Foam::codedFixedValueFvPatchField<Type>::codedFixedValueFvPatchField
449     const codedFixedValueFvPatchField<Type>& ptf,
450     const DimensionedField<Type, volMesh>& iF
453     fixedValueFvPatchField<Type>(ptf, iF),
454     dict_(ptf.dict_),
455     redirectType_(ptf.redirectType_),
456     oldLibPath_(ptf.oldLibPath_),
457     redirectPatchFieldPtr_()
461 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
463 template<class Type>
464 const Foam::fvPatchField<Type>&
465 Foam::codedFixedValueFvPatchField<Type>::redirectPatchField() const
467     if (!redirectPatchFieldPtr_.valid())
468     {
469         // Construct a patch
470         // Make sure to construct the patchfield with up-to-date value
472         OStringStream os;
473         os.writeKeyword("type") << redirectType_ << token::END_STATEMENT
474             << nl;
475         static_cast<const Field<Type>&>(*this).writeEntry("value", os);
476         IStringStream is(os.str());
477         dictionary dict(is);
479         redirectPatchFieldPtr_.set
480         (
481             fvPatchField<Type>::New
482             (
483                 this->patch(),
484                 this->dimensionedInternalField(),
485                 dict
486             ).ptr()
487         );
488     }
489     return redirectPatchFieldPtr_();
493 template<class Type>
494 void Foam::codedFixedValueFvPatchField<Type>::updateCoeffs()
496     if (this->updated())
497     {
498         return;
499     }
501     // Make sure library containing user-defined fvPatchField is up-to-date
502     updateLibrary();
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();
515 template<class Type>
516 void Foam::codedFixedValueFvPatchField<Type>::evaluate
518     const Pstream::commsTypes commsType
521     // Make sure library containing user-defined fvPatchField is up-to-date
522     updateLibrary();
524     const fvPatchField<Type>& fvp = redirectPatchField();
526     const_cast<fvPatchField<Type>&>(fvp).evaluate(commsType);
528     fixedValueFvPatchField<Type>::evaluate(commsType);
532 template<class Type>
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"))
540     {
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;
547     }
551 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
554 // ************************************************************************* //