electricPotential.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) 2021 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 "electricPotential.H"
29 #include "fvc.H"
30 #include "fvm.H"
31 #include "calculatedFvPatchField.H"
33 
34 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
35 
36 namespace Foam
37 {
38 namespace functionObjects
39 {
40  defineTypeNameAndDebug(electricPotential, 0);
41  addToRunTimeSelectionTable(functionObject, electricPotential, dictionary);
42 }
43 }
44 
45 
46 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
47 
49 Foam::functionObjects::electricPotential::operandField()
50 {
51  if (!foundObject<volScalarField>(fieldName_))
52  {
53  auto tfldPtr = tmp<volScalarField>::New
54  (
55  IOobject
56  (
57  fieldName_,
58  mesh_.time().timeName(),
59  mesh_,
62  ),
63  mesh_
64  );
65  store(fieldName_, tfldPtr);
66  }
67 
68  return lookupObjectRef<volScalarField>(fieldName_);
69 }
70 
71 
73 Foam::functionObjects::electricPotential::sigma() const
74 {
75  const IOobject sigmaIO
76  (
77  IOobject::scopedName(typeName, "sigma"),
78  mesh_.time().timeName(),
79  mesh_.time(),
82  false
83  );
84 
85  if (phases_.size())
86  {
87  tmp<volScalarField> tsigma = phases_[0]*sigmas_[0];
88 
89  for (label i = 1; i < phases_.size(); ++i)
90  {
91  tsigma.ref() += phases_[i]*sigmas_[i];
92  }
93 
95  (
96  sigmaIO,
97  tsigma,
99  );
100  }
101 
103  (
104  sigmaIO,
105  mesh_,
106  sigma_,
108  );
109 }
110 
111 
113 Foam::functionObjects::electricPotential::epsilonm() const
114 {
115  // Vacuum permittivity (aka the electric constant) [A^2 s^4/(kg m^3)]
117  (
119  8.8541878128e-12 // CODATA value
120  );
121 
122  const IOobject epsilonrIO
123  (
124  IOobject::scopedName(typeName, "epsilonr"),
125  mesh_.time().timeName(),
126  mesh_.time(),
129  false
130  );
131 
132  if (phases_.size())
133  {
134  tmp<volScalarField> tepsilonr = phases_[0]*epsilonrs_[0];
135 
136  for (label i = 1; i < phases_.size(); ++i)
137  {
138  tepsilonr.ref() += phases_[i]*epsilonrs_[i];
139  }
140 
142  (
143  epsilonrIO,
144  epsilon0*tepsilonr,
146  );
147  }
148 
150  (
151  epsilonrIO,
152  mesh_,
153  epsilon0*epsilonr_,
155  );
156 }
157 
158 
159 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
160 
161 Foam::functionObjects::electricPotential::electricPotential
162 (
163  const word& name,
164  const Time& runTime,
165  const dictionary& dict
166 )
167 :
169  phasesDict_(dict.subOrEmptyDict("phases")),
170  phaseNames_(),
171  phases_(),
172  sigmas_(),
173  sigma_
174  (
176  (
178  dict.getCheckOrDefault<scalar>
179  (
180  "sigma",
181  scalar(1),
182  scalarMinMax::ge(SMALL)
183  )
184  )
185  ),
186  epsilonrs_(),
187  epsilonr_
188  (
190  (
191  dimless,
192  dict.getCheckOrDefault<scalar>
193  (
194  "epsilonr",
195  scalar(1),
196  scalarMinMax::ge(SMALL)
197  )
198  )
199  ),
200  fieldName_
201  (
202  dict.getOrDefault<word>
203  (
204  "field",
205  IOobject::scopedName(typeName, "V")
206  )
207  ),
208  nCorr_(1),
209  writeDerivedFields_(false)
210 {
211  read(dict);
212 
213  // Force creation of transported field so any BCs using it can
214  // look it up
215  volScalarField& eV = operandField();
217 }
218 
219 
220 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
221 
223 {
225  {
226  Log << type() << " read: " << name() << endl;
227 
228  dict.readIfPresent("sigma", sigma_);
229  dict.readIfPresent("epsilonr", epsilonr_);
230  dict.readIfPresent("nCorr", nCorr_);
231  dict.readIfPresent("writeDerivedFields", writeDerivedFields_);
232 
233  // If flow is multiphase
234  if (!phasesDict_.empty())
235  {
236  phaseNames_.setSize(phasesDict_.size());
237  phases_.setSize(phasesDict_.size());
238  sigmas_.setSize(phasesDict_.size());
239 
240  if (writeDerivedFields_)
241  {
242  epsilonrs_.setSize(phasesDict_.size());
243  }
244 
245  label phasei = 0;
246  for (const entry& dEntry : phasesDict_)
247  {
248  const word& key = dEntry.keyword();
249 
250  if (!dEntry.isDict())
251  {
252  FatalIOErrorInFunction(phasesDict_)
253  << "Entry " << key << " is not a dictionary" << nl
254  << exit(FatalIOError);
255  }
256 
257  const dictionary& subDict = dEntry.dict();
258 
259  phaseNames_[phasei] = key;
260 
261  sigmas_.set
262  (
263  phasei,
265  (
267  subDict.getCheck<scalar>
268  (
269  "sigma",
270  scalarMinMax::ge(SMALL)
271  )
272  )
273  );
274 
275  if (writeDerivedFields_)
276  {
277  epsilonrs_.set
278  (
279  phasei,
281  (
282  dimless,
283  subDict.getCheck<scalar>
284  (
285  "epsilonr",
286  scalarMinMax::ge(SMALL)
287  )
288  )
289  );
290  }
291 
292  ++phasei;
293  }
294 
295  forAll(phaseNames_, i)
296  {
297  phases_.set
298  (
299  i,
300  mesh_.getObjectPtr<volScalarField>(phaseNames_[i])
301  );
302  }
303  }
304 
305  return true;
306  }
307 
308  return false;
309 }
310 
311 
313 {
314  Log << type() << " execute: " << name() << endl;
315 
316  tmp<volScalarField> tsigma = this->sigma();
317  const volScalarField& sigma = tsigma();
318 
319  volScalarField& eV = operandField();
320 
321  for (label i = 1; i <= nCorr_; ++i)
322  {
323  fvScalarMatrix eVEqn
324  (
325  - fvm::laplacian(sigma, eV)
326  );
327 
328  eVEqn.relax();
329 
330  eVEqn.solve();
331  }
333  Log << endl;
334 
335  return true;
336 }
337 
338 
340 {
341  Log << type() << " write: " << name() << nl
342  << tab << fieldName_
343  << endl;
344 
345  volScalarField& eV = operandField();
346 
347  if (writeDerivedFields_)
348  {
349  // Write the electric field
350  const volVectorField E
351  (
352  IOobject
353  (
354  IOobject::scopedName(typeName, "E"),
355  mesh_.time().timeName(),
356  mesh_.time(),
359  false
360  ),
361  -fvc::grad(eV),
363  );
364 
365  Log << tab << E.name() << endl;
366 
367  E.write();
368 
369 
370  // Write the current density field
371  tmp<volScalarField> tsigma = this->sigma();
372 
373  auto eJ = tmp<volVectorField>::New
374  (
375  IOobject
376  (
377  IOobject::scopedName(typeName, "J"),
378  mesh_.time().timeName(),
379  mesh_.time(),
382  false
383  ),
384  -tsigma*fvc::grad(eV),
386  );
387 
388  Log << tab << eJ().name() << endl;
389 
390  eJ->write();
391 
392 
393  // Write the free-charge density field
394  tmp<volScalarField> tepsilonm = this->epsilonm();
395 
396  auto erho = tmp<volScalarField>::New
397  (
398  IOobject
399  (
400  IOobject::scopedName(typeName, "rho"),
401  mesh_.time().timeName(),
402  mesh_.time(),
405  false
406  ),
407  fvc::div(tepsilonm*E),
409  );
410 
411  Log << tab << erho().name() << endl;
412 
413  erho->write();
414  }
415 
416  eV.write();
417 
418  return true;
419 }
420 
421 
422 // ************************************************************************* //
virtual bool write()
Write the function object output.
dictionary dict
tmp< GeometricField< typename outerProduct< vector, Type >::type, fvPatchField, volMesh >> grad(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
Definition: fvcGrad.C:47
defineTypeNameAndDebug(ObukhovLength, 0)
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
label phasei
Definition: pEqn.H:27
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:120
dimensionedSymmTensor sqr(const dimensionedVector &dv)
tmp< GeometricField< Type, fvPatchField, volMesh > > div(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
Definition: fvcDiv.C:42
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:49
engineTime & runTime
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:487
constexpr char tab
The tab &#39;\t&#39; character(0x09)
Definition: Ostream.H:48
Ignore writing from objectRegistry::writeObject()
const dimensionSet dimless
Dimensionless.
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:361
const dimensionedScalar epsilon0
Electric constant: default SI units: [F/m].
dimensionedScalar sigma("sigma", dimMass/sqr(dimTime), transportProperties)
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:69
Macros for easy insertion into run-time selection tables.
virtual bool read(const dictionary &dict)
Read the function object data.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:413
GeometricField< scalar, fvPatchField, volMesh > volScalarField
Definition: volFieldsFwd.H:84
static const char *const typeName
Typename for Field.
Definition: Field.H:86
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: POSIX.C:752
static word scopedName(const std::string &scope, const word &name)
Create scope:name or scope_name string.
Definition: IOobjectI.H:40
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:52
A class for handling words, derived from Foam::string.
Definition: word.H:63
bool store(word &fieldName, const tmp< ObjectType > &tfield, bool cacheable=false)
Store the field in the (sub) objectRegistry under the given name.
static MinMax< scalar > ge(const scalar &minVal)
A semi-infinite range from minVal to the type max.
Definition: MinMaxI.H:24
This boundary condition is not designed to be evaluated; it is assmued that the value is assigned via...
static tmp< T > New(Args &&... args)
Construct tmp with forwarding arguments.
Definition: tmp.H:203
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
A special matrix type and solver, designed for finite volume solutions of scalar equations. Face addressing is used to make all matrix assembly and solution loops vectorise.
Definition: fvPatchField.H:64
virtual bool execute()
Calculate the function object.
SolverPerformance< Type > solve(const dictionary &)
Solve returning the solution statistics.
static word timeName(const scalar t, const int precision=precision_)
Return time name of given scalar time formatted with the given precision.
Definition: Time.C:760
addToRunTimeSelectionTable(functionObject, ObukhovLength, dictionary)
void relax(const scalar alpha)
Relax matrix (for steady-state solution).
Definition: fvMatrix.C:1100
dimensionedScalar pow3(const dimensionedScalar &ds)
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:50
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:607
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
tmp< fvMatrix< Type > > laplacian(const GeometricField< Type, fvPatchField, volMesh > &vf, const word &name)
Definition: fvmLaplacian.C:41
auto key(const Type &t) -> typename std::enable_if< std::is_enum< Type >::value, typename std::underlying_type< Type >::type >::type
Definition: foamGltfBase.H:103
const dimensionSet dimCurrent(0, 0, 0, 0, 0, 1, 0)
Definition: dimensionSets.H:54
dimensionedScalar pow4(const dimensionedScalar &ds)
Nothing to be read.
#define Log
Definition: PDRblock.C:28
const dimensionSet dimTime(0, 0, 1, 0, 0, 0, 0)
Definition: dimensionSets.H:51
void correctBoundaryConditions()
Correct boundary field.
virtual bool read(const dictionary &dict)
Read optional controls.
Specialization of Foam::functionObject for an Foam::fvMesh, providing a reference to the Foam::fvMesh...
const dimensionSet dimMass(1, 0, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:49
A class for managing temporary objects.
Definition: HashPtrTable.H:50
virtual bool write(const bool valid=true) const
Write using setting from DB.
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:166
const fvMesh & mesh_
Reference to the fvMesh.
Namespace for OpenFOAM.
A keyword and a list of tokens is an &#39;entry&#39;.
Definition: entry.H:63
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...