Merge branch 'master' of ssh://git.code.sf.net/p/foam-extend/foam-extend-3.2
[foam-extend-3.2.git] / src / foam / db / functionObjects / functionObjectList / functionObjectList.C
blob02d4814b3a942f5bb9b8e8f995b7c24d3e531100
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | foam-extend: Open Source CFD
4    \\    /   O peration     | Version:     3.2
5     \\  /    A nd           | Web:         http://www.foam-extend.org
6      \\/     M anipulation  | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
8 License
9     This file is part of foam-extend.
11     foam-extend is free software: you can redistribute it and/or modify it
12     under the terms of the GNU General Public License as published by the
13     Free Software Foundation, either version 3 of the License, or (at your
14     option) any later version.
16     foam-extend is distributed in the hope that it will be useful, but
17     WITHOUT ANY WARRANTY; without even the implied warranty of
18     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19     General Public License for more details.
21     You should have received a copy of the GNU General Public License
22     along with foam-extend.  If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "functionObjectList.H"
27 #include "objectRegistry.H"
29 #include "profiling.H"
31 // * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * * //
33 Foam::functionObject*
34 Foam::functionObjectList::remove(const word& key, label& oldIndex)
36     functionObject* ptr = 0;
38     // Find index of existing functionObject
39     HashTable<label>::iterator fnd = indices_.find(key);
41     if (fnd != indices_.end())
42     {
43         oldIndex = fnd();
45         // retrieve the pointer and remove it from the old list
46         ptr = this->set(oldIndex, 0).ptr();
47         indices_.erase(fnd);
48     }
49     else
50     {
51         oldIndex = -1;
52     }
54     return ptr;
58 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
60 Foam::functionObjectList::functionObjectList
62     const Time& t,
63     const bool execution
66     PtrList<functionObject>(),
67     digests_(),
68     indices_(),
69     time_(t),
70     parentDict_(t.controlDict()),
71     execution_(execution),
72     updated_(false)
76 Foam::functionObjectList::functionObjectList
78     const Time& t,
79     const dictionary& parentDict,
80     const bool execution
83     PtrList<functionObject>(),
84     digests_(),
85     indices_(),
86     time_(t),
87     parentDict_(parentDict),
88     execution_(execution),
89     updated_(false)
93 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
95 Foam::functionObjectList::~functionObjectList()
99 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
101 void Foam::functionObjectList::clear()
103     PtrList<functionObject>::clear();
104     digests_.clear();
105     indices_.clear();
106     updated_ = false;
110 void Foam::functionObjectList::on()
112     execution_ = true;
116 void Foam::functionObjectList::off()
118     // for safety, also force a read() when execution is turned back on
119     updated_ = execution_ = false;
123 bool Foam::functionObjectList::status() const
125     return execution_;
129 bool Foam::functionObjectList::start()
131     return read();
135 bool Foam::functionObjectList::execute()
137     bool ok = true;
139     if (execution_)
140     {
141         if (!updated_)
142         {
143             read();
144         }
146         forAllIter
147         (
148             PtrList<functionObject>,
149             static_cast<PtrList<functionObject>&>(*this),
150             iter
151         )
152         {
153             addProfile2(fo,"FO::"+(*iter).name()+"::execute");
155             ok = iter().execute() && ok;
156         }
157     }
159     return ok;
163 bool Foam::functionObjectList::end()
165     bool ok = true;
167     if (execution_)
168     {
169         if (!updated_)
170         {
171             read();
172         }
174         forAllIter
175         (
176             PtrList<functionObject>,
177             static_cast<PtrList<functionObject>&>(*this),
178             iter
179         )
180         {
181             addProfile2(fo,"FO::"+(*iter).name()+"::end");
183             ok = iter().end() && ok;
184         }
185     }
187     return ok;
191 bool Foam::functionObjectList::read()
193     bool ok = true;
194     updated_ = execution_;
196     addProfile2(fo,"functionObjectList::read");
198     // avoid reading/initializing if execution is off
199     if (!execution_)
200     {
201         return ok;
202     }
204     // Update existing and add new functionObjects
205     const entry* entryPtr = parentDict_.lookupEntryPtr("functions",false,false);
206     if (entryPtr)
207     {
208         PtrList<functionObject> newPtrs;
209         List<SHA1Digest> newDigs;
210         HashTable<label> newIndices;
212         label nFunc = 0;
214         if (entryPtr->isDict())
215         {
216             // a dictionary of functionObjects
217             const dictionary& functionDicts = entryPtr->dict();
219             newPtrs.setSize(functionDicts.size());
220             newDigs.setSize(functionDicts.size());
222             forAllConstIter(dictionary, functionDicts, iter)
223             {
224                 // safety:
225                 if (!iter().isDict())
226                 {
227                     continue;
228                 }
229                 const word& key = iter().keyword();
230                 const dictionary& dict = iter().dict();
232                 newDigs[nFunc] = dict.digest();
234                 label oldIndex;
235                 functionObject* objPtr = remove(key, oldIndex);
236                 if (objPtr)
237                 {
238                     // an existing functionObject, and dictionary changed
239                     if (newDigs[nFunc] != digests_[oldIndex])
240                     {
241                         addProfile2(fo,"FO::"+objPtr->name()+"::read");
243                         ok = objPtr->read(dict) && ok;
244                     }
245                 }
246                 else
247                 {
248                     // new functionObject
249                     objPtr = functionObject::New(key, time_, dict).ptr();
251                     addProfile2(fo,"FO::"+objPtr->name()+"::start");
253                     ok = objPtr->start() && ok;
254                 }
256                 newPtrs.set(nFunc, objPtr);
257                 newIndices.insert(key, nFunc);
258                 nFunc++;
259             }
260         }
261         else
262         {
263             // a list of functionObjects
264             PtrList<entry> functionDicts(entryPtr->stream());
266             newPtrs.setSize(functionDicts.size());
267             newDigs.setSize(functionDicts.size());
269             forAllIter(PtrList<entry>, functionDicts, iter)
270             {
271                 // safety:
272                 if (!iter().isDict())
273                 {
274                     continue;
275                 }
276                 const word& key = iter().keyword();
277                 const dictionary& dict = iter().dict();
279                 newDigs[nFunc] = dict.digest();
281                 label oldIndex;
282                 functionObject* objPtr = remove(key, oldIndex);
283                 if (objPtr)
284                 {
285                     // an existing functionObject, and dictionary changed
286                     if (newDigs[nFunc] != digests_[oldIndex])
287                     {
288                         ok = objPtr->read(dict) && ok;
289                     }
290                 }
291                 else
292                 {
293                     // new functionObject
294                     objPtr = functionObject::New(key, time_, dict).ptr();
295                     ok = objPtr->start() && ok;
296                 }
298                 newPtrs.set(nFunc, objPtr);
299                 newIndices.insert(key, nFunc);
300                 nFunc++;
301             }
302         }
304         // safety:
305         newPtrs.setSize(nFunc);
306         newDigs.setSize(nFunc);
308         // updating the PtrList of functionObjects also deletes any existing,
309         // but unused functionObjects
310         PtrList<functionObject>::transfer(newPtrs);
311         digests_.transfer(newDigs);
312         indices_.transfer(newIndices);
313     }
314     else
315     {
316         PtrList<functionObject>::clear();
317         digests_.clear();
318         indices_.clear();
319     }
321     return ok;
325 // ************************************************************************* //