From a820021a0a0ad80faeff137a294e25bcfec6e95a Mon Sep 17 00:00:00 2001 From: graham Date: Sun, 6 Dec 2009 12:20:38 +0000 Subject: [PATCH 001/250] Adding moment of inertia code, unused as yet. --- .../momentOfInertia/momentOfInertia.C | 403 ++++++++++++++++++ .../momentOfInertia/momentOfInertia.H | 75 ++++ src/meshTools/momentOfInertia/volInt.ps.gz | Bin 0 -> 70333 bytes .../momentOfInertia/volumeIntegration/README | 146 +++++++ .../momentOfInertia/volumeIntegration/cube | 21 + .../momentOfInertia/volumeIntegration/icosa | 38 ++ .../momentOfInertia/volumeIntegration/tetra | 16 + .../volumeIntegration/volInt.c | 380 +++++++++++++++++ 8 files changed, 1079 insertions(+) create mode 100644 src/meshTools/momentOfInertia/momentOfInertia.C create mode 100644 src/meshTools/momentOfInertia/momentOfInertia.H create mode 100644 src/meshTools/momentOfInertia/volInt.ps.gz create mode 100644 src/meshTools/momentOfInertia/volumeIntegration/README create mode 100644 src/meshTools/momentOfInertia/volumeIntegration/cube create mode 100644 src/meshTools/momentOfInertia/volumeIntegration/icosa create mode 100644 src/meshTools/momentOfInertia/volumeIntegration/tetra create mode 100644 src/meshTools/momentOfInertia/volumeIntegration/volInt.c diff --git a/src/meshTools/momentOfInertia/momentOfInertia.C b/src/meshTools/momentOfInertia/momentOfInertia.C new file mode 100644 index 0000000000..5207850172 --- /dev/null +++ b/src/meshTools/momentOfInertia/momentOfInertia.C @@ -0,0 +1,403 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2007-2009 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Class + momentOfInertia + +Description + Reimplementation of volInt.c by Brian Mirtich. + * mirtich@cs.berkeley.edu * + * http://www.cs.berkeley.edu/~mirtich * + +------------------------------------------------------------------------------- +*/ + +#include "momentOfInertia.H" +//#include "pyramidPointFaceRef.H" + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +//Foam::tensor Foam::momentOfInertia +//( +// const pointField& points, +// const faceList& faces, +// const cell& cFaces, +// const point& cc +//) +//{ +// tensor t(tensor::zero); +// +// forAll(cFaces, i) +// { +// const face& f = faces[cFaces[i]]; +// +// scalar pyrVol = pyramidPointFaceRef(f, cc).mag(points); +// +// vector pyrCentre = pyramidPointFaceRef(f, cc).centre(points); +// +// vector d = pyrCentre - cc; +// +// t.xx() += pyrVol*(sqr(d.y()) + sqr(d.z())); +// t.yy() += pyrVol*(sqr(d.x()) + sqr(d.z())); +// t.zz() += pyrVol*(sqr(d.x()) + sqr(d.y())); +// +// t.xy() -= pyrVol*d.x()*d.y(); +// t.xz() -= pyrVol*d.x()*d.z(); +// t.yz() -= pyrVol*d.y()*d.z(); +// } +// +// // Symmetric +// t.yx() = t.xy(); +// t.zx() = t.xz(); +// t.zy() = t.yz(); +// +// return t; +//} + + +#define sqr(x) ((x)*(x)) +#define pow3(x) ((x)*(x)*(x)) + +// compute various integrations over projection of face +void Foam::compProjectionIntegrals +( + const pointField& points, + const face& f, + const direction A, + const direction B, + + scalar& P1, + scalar& Pa, + scalar& Pb, + scalar& Paa, + scalar& Pab, + scalar& Pbb, + scalar& Paaa, + scalar& Paab, + scalar& Pabb, + scalar& Pbbb +) +{ + P1 = Pa = Pb = Paa = Pab = Pbb = Paaa = Paab = Pabb = Pbbb = 0.0; + + forAll(f, i) + { + scalar a0 = points[f[i]][A]; + scalar b0 = points[f[i]][B]; + scalar a1 = points[f[(i+1) % f.size()]][A]; + scalar b1 = points[f[(i+1) % f.size()]][B]; + scalar da = a1 - a0; + scalar db = b1 - b0; + + scalar a0_2 = a0 * a0; + scalar a0_3 = a0_2 * a0; + scalar a0_4 = a0_3 * a0; + + scalar b0_2 = b0 * b0; + scalar b0_3 = b0_2 * b0; + scalar b0_4 = b0_3 * b0; + + scalar a1_2 = a1 * a1; + scalar a1_3 = a1_2 * a1; + + scalar b1_2 = b1 * b1; + scalar b1_3 = b1_2 * b1; + + scalar C1 = a1 + a0; + + scalar Ca = a1*C1 + a0_2; + scalar Caa = a1*Ca + a0_3; + scalar Caaa = a1*Caa + a0_4; + + scalar Cb = b1*(b1 + b0) + b0_2; + scalar Cbb = b1*Cb + b0_3; + scalar Cbbb = b1*Cbb + b0_4; + + scalar Cab = 3*a1_2 + 2*a1*a0 + a0_2; + scalar Kab = a1_2 + 2*a1*a0 + 3*a0_2; + + scalar Caab = a0*Cab + 4*a1_3; + scalar Kaab = a1*Kab + 4*a0_3; + + scalar Cabb = 4*b1_3 + 3*b1_2*b0 + 2*b1*b0_2 + b0_3; + scalar Kabb = b1_3 + 2*b1_2*b0 + 3*b1*b0_2 + 4*b0_3; + + P1 += db*C1; + Pa += db*Ca; + Paa += db*Caa; + Paaa += db*Caaa; + Pb += da*Cb; + Pbb += da*Cbb; + Pbbb += da*Cbbb; + Pab += db*(b1*Cab + b0*Kab); + Paab += db*(b1*Caab + b0*Kaab); + Pabb += da*(a1*Cabb + a0*Kabb); + } + + P1 /= 2.0; + Pa /= 6.0; + Paa /= 12.0; + Paaa /= 20.0; + Pb /= -6.0; + Pbb /= -12.0; + Pbbb /= -20.0; + Pab /= 24.0; + Paab /= 60.0; + Pabb /= -60.0; +} + + +void Foam::compFaceIntegrals +( + const pointField& points, + const face& f, + const vector& n, + const scalar w, + const direction A, + const direction B, + const direction C, + + scalar& Fa, + scalar& Fb, + scalar& Fc, + scalar& Faa, + scalar& Fbb, + scalar& Fcc, + scalar& Faaa, + scalar& Fbbb, + scalar& Fccc, + scalar& Faab, + scalar& Fbbc, + scalar& Fcca +) +{ + scalar P1, Pa, Pb, Paa, Pab, Pbb, Paaa, Paab, Pabb, Pbbb; + + compProjectionIntegrals + ( + points, + f, + A, + B, + + P1, + Pa, + Pb, + Paa, + Pab, + Pbb, + Paaa, + Paab, + Pabb, + Pbbb + ); + + scalar k1 = 1 / n[C]; + scalar k2 = k1 * k1; + scalar k3 = k2 * k1; + scalar k4 = k3 * k1; + + Fa = k1 * Pa; + Fb = k1 * Pb; + Fc = -k2 * (n[A]*Pa + n[B]*Pb + w*P1); + + Faa = k1 * Paa; + Fbb = k1 * Pbb; + Fcc = k3 * (sqr(n[A])*Paa + 2*n[A]*n[B]*Pab + sqr(n[B])*Pbb + + w*(2*(n[A]*Pa + n[B]*Pb) + w*P1)); + + Faaa = k1 * Paaa; + Fbbb = k1 * Pbbb; + Fccc = -k4 * (pow3(n[A])*Paaa + 3*sqr(n[A])*n[B]*Paab + + 3*n[A]*sqr(n[B])*Pabb + pow3(n[B])*Pbbb + + 3*w*(sqr(n[A])*Paa + 2*n[A]*n[B]*Pab + sqr(n[B])*Pbb) + + w*w*(3*(n[A]*Pa + n[B]*Pb) + w*P1)); + + Faab = k1 * Paab; + Fbbc = -k2 * (n[A]*Pabb + n[B]*Pbbb + w*Pbb); + Fcca = k3 * (sqr(n[A])*Paaa + 2*n[A]*n[B]*Paab + sqr(n[B])*Pabb + + w*(2*(n[A]*Paa + n[B]*Pab) + w*Pa)); +} + + +void Foam::compVolumeIntegrals +( + const pointField& points, + const faceList& faces, + const cell& cFaces, + const vectorField& fNorm, + const scalarField& fW, + + scalar& T0, + vector& T1, + vector& T2, + vector& TP +) +{ + T0 = 0; + T1 = vector::zero; + T2 = vector::zero; + TP = vector::zero; + + forAll(cFaces, i) + { + const vector& n = fNorm[i]; + + scalar nx = mag(n[0]); + scalar ny = mag(n[1]); + scalar nz = mag(n[2]); + + direction A, B, C; + + if (nx > ny && nx > nz) + { + C = 0; + } + else + { + C = (ny > nz) ? 1 : 2; + } + + A = (C + 1) % 3; + B = (A + 1) % 3; + + scalar Fa, Fb, Fc, Faa, Fbb, Fcc, Faaa, Fbbb, Fccc, Faab, Fbbc, Fcca; + compFaceIntegrals + ( + points, + faces[cFaces[i]], + n, + fW[i], + A, + B, + C, + + Fa, + Fb, + Fc, + Faa, + Fbb, + Fcc, + Faaa, + Fbbb, + Fccc, + Faab, + Fbbc, + Fcca + ); + + T0 += n[0] * ((A == 0) ? Fa : ((B == 0) ? Fb : Fc)); + + T1[A] += n[A] * Faa; + T1[B] += n[B] * Fbb; + T1[C] += n[C] * Fcc; + + T2[A] += n[A] * Faaa; + T2[B] += n[B] * Fbbb; + T2[C] += n[C] * Fccc; + + TP[A] += n[A] * Faab; + TP[B] += n[B] * Fbbc; + TP[C] += n[C] * Fcca; + } + + T1 /= 2; + T2 /= 3; + TP /= 2; +} + + +// Calculate +// - r: centre of mass +// - J: inertia around origin (point 0,0,0) +void Foam::momentOfIntertia +( + const pointField& points, + const faceList& faces, + const cell& cFaces, + point& r, + tensor& J +) +{ + // Face normals + vectorField fNorm(cFaces.size()); + scalarField fW(cFaces.size()); + + forAll(cFaces, i) + { + label faceI = cFaces[i]; + + const face& f = faces[faceI]; + + fNorm[i] = f.normal(points); + fNorm[i] /= mag(fNorm[i]) + VSMALL; + + fW[i] = - (fNorm[i] & points[f[0]]); + } + + + scalar T0; + vector T1, T2, TP; + + compVolumeIntegrals + ( + points, + faces, + cFaces, + fNorm, + fW, + + T0, + T1, + T2, + TP + ); + + const scalar density = 1.0; /* assume unit density */ + + scalar mass = density * T0; + + /* compute center of mass */ + r = T1 / T0; + + /* compute inertia tensor */ + J.xx() = density * (T2[1] + T2[2]); + J.yy() = density * (T2[2] + T2[0]); + J.zz() = density * (T2[0] + T2[1]); + J.xy() = J.yx() = - density * TP[0]; + J.yz() = J.zy() = - density * TP[1]; + J.zx() = J.xz() = - density * TP[2]; + + ///* translate inertia tensor to center of mass */ + //J[XX] -= mass * (r[1]*r[1] + r[2]*r[2]); + //J[YY] -= mass * (r[2]*r[2] + r[0]*r[0]); + //J[ZZ] -= mass * (r[0]*r[0] + r[1]*r[1]); + //J[XY] = J[YX] += mass * r[0] * r[1]; + //J[YZ] = J[ZY] += mass * r[1] * r[2]; + //J[ZX] = J[XZ] += mass * r[2] * r[0]; +} + + + +// ************************************************************************* // diff --git a/src/meshTools/momentOfInertia/momentOfInertia.H b/src/meshTools/momentOfInertia/momentOfInertia.H new file mode 100644 index 0000000000..66a8d357ad --- /dev/null +++ b/src/meshTools/momentOfInertia/momentOfInertia.H @@ -0,0 +1,75 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2007-2009 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Class + momentOfInertia + +Description + +SourceFiles + momentOfInertia.H + +\*---------------------------------------------------------------------------*/ + +#ifndef momentOfInertia_H +#define momentOfInertia_H + +#include "tensor.H" +#include "primitiveMesh.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +////- Moment of inertia around cell centre for single cell. +//tensor momentOfInertia +//( +// const pointField&, +// const faceList&, +// const cell&, +// const point& cc +//); + +// Calculate +// - centre of mass +// - inertia tensor around (0,0,0) +void momentOfIntertia +( + const pointField&, + const faceList&, + const cell&, + point& r, + tensor& Jorigin +); + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/meshTools/momentOfInertia/volInt.ps.gz b/src/meshTools/momentOfInertia/volInt.ps.gz new file mode 100644 index 0000000000000000000000000000000000000000..19fb295421229e04ce4ff1a27fedb6d60244dd3a GIT binary patch literal 70333 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 literal 0 HcmV?d00001 diff --git a/src/meshTools/momentOfInertia/volumeIntegration/README b/src/meshTools/momentOfInertia/volumeIntegration/README new file mode 100644 index 0000000000..dadca677b7 --- /dev/null +++ b/src/meshTools/momentOfInertia/volumeIntegration/README @@ -0,0 +1,146 @@ +1. OVERVIEW + + This code accompanies the paper: + + Brian Mirtich, "Fast and Accurate Computation of + Polyhedral Mass Properties," journal of graphics + tools, volume 1, number 2, 1996. + + It computes the ten volume integrals needed for + determining the center of mass, moments of + inertia, and products of inertia for a uniform + density polyhedron. From this information, a + body frame can be computed. + + To compile the program, use an ANSI compiler, and + type something like + + % cc volInt.c -O2 -lm -o volInt + + + Revision history + + 26 Jan 1996 Program creation. + + 3 Aug 1996 Corrected bug arising when polyhedron density + is not 1.0. Changes confined to function main(). + Thanks to Zoran Popovic for catching this one. + + + +2. POLYHEDRON GEOMETRY FILES + + The program reads a data file specified on the + command line. This data file describes the + geometry of a polyhedron, and has the following + format: + + N + + x_0 y_0 z_0 + x_1 y_1 z_1 + . + . + . + x_{N-1} y_{N-1} z_{N-1} + + M + + k1 v_{1,1} v_{1,2} ... v_{1,k1} + k2 v_{2,1} v_{2,2} ... v_{2,k2} + . + . + . + kM v_{M,1} v_{M,2} ... v_{M,kM} + + + where: + N number of vertices on polyhedron + x_i y_i z_i x, y, and z coordinates of ith vertex + M number of faces on polyhedron + ki number of vertices on ith face + v_{i,j} jth vertex on ith face + + In English: + + First the number of vertices are specified. Next + the vertices are defined by listing the 3 + coordinates of each one. Next the number of faces + are specified. Finally, the faces themselves are + specified. A face is specified by first giving + the number of vertices around the polygonal face, + followed by the (integer) indices of these + vertices. When specifying indices, note that + they must be given in counter-clockwise order + (when looking at the face from outside the + polyhedron), and the vertices are indexed from 0 + to N-1 for a polyhedron with N faces. + + White space can be inserted (or not) as desired. + Three example polyhedron geometry files are included: + + cube A cube, 20 units on a side, centered at + the origin and aligned with the coordinate axes. + + tetra A tetrahedron formed by taking the convex + hull of the origin, and the points (5,0,0), + (0,4,0), and (0,0,3). + + icosa An icosahedron with vertices lying on the unit + sphere, centered at the origin. + + + +3. RUNNING THE PROGRAM + + Simply type, + + % volInt + + The program will read in the geometry of the + polyhedron, and the print out the ten volume + integrals. + + The program also computes some of the mass + properties which may be inferred from the volume + integrals. A density of 1.0 is assumed, although + this may be changed in function main(). The + center of mass is computed as well as the inertia + tensor relative to a frame with origin at the + center of mass. Note, however, that this matrix + may not be diagonal. If not, a diagonalization + routine must be performed, to determine the + orientation of the true body frame relative to + the original model frame. The Jacobi method + works quite well (see Numerical Recipes in C by + Press, et. al.). + + + +4. DISCLAIMERS + + 1. The volume integration code has been written + to match the development and algorithms presented + in the paper, and not with maximum optimization + in mind. While inherently very efficient, a few + more cycles can be squeezed out of the algorithm. + This is left as an exercise. :) + + 2. Don't like global variables? The three + procedures which evaluate the volume integrals + can be combined into a single procedure with two + nested loops. In addition to providing some + speedup, all of the global variables can then be + made local. + + 3. The polyhedron data structure used by the + program is admittedly lame; much better schemes + are possible. The idea here is just to give the + basic integral evaluation code, which will have + to be adjusted for other polyhedron data + structures. + + 4. There is no error checking for the input + files. Be careful. Note the hard limits + #defined for the number of vertices, number of + faces, and number of vertices per faces. diff --git a/src/meshTools/momentOfInertia/volumeIntegration/cube b/src/meshTools/momentOfInertia/volumeIntegration/cube new file mode 100644 index 0000000000..07ab26ad16 --- /dev/null +++ b/src/meshTools/momentOfInertia/volumeIntegration/cube @@ -0,0 +1,21 @@ +8 + +-10 -10 -10 ++10 -10 -10 ++10 +10 -10 +-10 +10 -10 +-10 -10 +10 ++10 -10 +10 ++10 +10 +10 +-10 +10 +10 + +6 + +4 0 3 2 1 +4 4 5 6 7 +4 0 1 5 4 +4 6 2 3 7 +4 1 2 6 5 +4 0 4 7 3 + + diff --git a/src/meshTools/momentOfInertia/volumeIntegration/icosa b/src/meshTools/momentOfInertia/volumeIntegration/icosa new file mode 100644 index 0000000000..16339ece89 --- /dev/null +++ b/src/meshTools/momentOfInertia/volumeIntegration/icosa @@ -0,0 +1,38 @@ +12 + ++0.00000000 +0.00000000 +1.00000000 ++0.00000000 +0.00000000 -1.00000000 ++0.89442719 +0.00000000 +0.44721360 ++0.27639320 +0.85065081 +0.44721360 +-0.72360680 +0.52573111 +0.44721360 +-0.72360680 -0.52573111 +0.44721360 ++0.27639320 -0.85065081 +0.44721360 ++0.72360680 +0.52573111 -0.44721360 +-0.27639320 +0.85065081 -0.44721360 +-0.89442719 +0.00000000 -0.44721360 +-0.27639320 -0.85065081 -0.44721360 ++0.72360680 -0.52573111 -0.44721360 + +20 + +3 6 11 2 +3 3 2 7 +3 7 2 11 +3 0 2 3 +3 0 6 2 +3 10 1 11 +3 1 7 11 +3 10 11 6 +3 8 7 1 +3 8 3 7 +3 5 10 6 +3 5 6 0 +3 4 3 8 +3 4 0 3 +3 9 8 1 +3 9 1 10 +3 4 5 0 +3 9 10 5 +3 9 5 4 +3 9 4 8 + diff --git a/src/meshTools/momentOfInertia/volumeIntegration/tetra b/src/meshTools/momentOfInertia/volumeIntegration/tetra new file mode 100644 index 0000000000..159e5a2bf8 --- /dev/null +++ b/src/meshTools/momentOfInertia/volumeIntegration/tetra @@ -0,0 +1,16 @@ +4 + +0 0 0 +5 0 0 +0 4 0 +0 0 3 + +4 + +3 0 3 2 +3 3 0 1 +3 2 1 0 +3 1 2 3 + + + diff --git a/src/meshTools/momentOfInertia/volumeIntegration/volInt.c b/src/meshTools/momentOfInertia/volumeIntegration/volInt.c new file mode 100644 index 0000000000..7601655488 --- /dev/null +++ b/src/meshTools/momentOfInertia/volumeIntegration/volInt.c @@ -0,0 +1,380 @@ + + + /******************************************************* + * * + * volInt.c * + * * + * This code computes volume integrals needed for * + * determining mass properties of polyhedral bodies. * + * * + * For more information, see the accompanying README * + * file, and the paper * + * * + * Brian Mirtich, "Fast and Accurate Computation of * + * Polyhedral Mass Properties," journal of graphics * + * tools, volume 1, number 1, 1996. * + * * + * This source code is public domain, and may be used * + * in any way, shape or form, free of charge. * + * * + * Copyright 1995 by Brian Mirtich * + * * + * mirtich@cs.berkeley.edu * + * http://www.cs.berkeley.edu/~mirtich * + * * + *******************************************************/ + +/* + Revision history + + 26 Jan 1996 Program creation. + + 3 Aug 1996 Corrected bug arising when polyhedron density + is not 1.0. Changes confined to function main(). + Thanks to Zoran Popovic for catching this one. + + 27 May 1997 Corrected sign error in translation of inertia + product terms to center of mass frame. Changes + confined to function main(). Thanks to + Chris Hecker. +*/ + + + +#include +#include +#include + +/* + ============================================================================ + constants + ============================================================================ +*/ + +#define MAX_VERTS 100 /* maximum number of polyhedral vertices */ +#define MAX_FACES 100 /* maximum number of polyhedral faces */ +#define MAX_POLYGON_SZ 10 /* maximum number of verts per polygonal face */ + +#define X 0 +#define Y 1 +#define Z 2 + +/* + ============================================================================ + macros + ============================================================================ +*/ + +#define SQR(x) ((x)*(x)) +#define CUBE(x) ((x)*(x)*(x)) + +/* + ============================================================================ + data structures + ============================================================================ +*/ + +typedef struct { + int numVerts; + double norm[3]; + double w; + int verts[MAX_POLYGON_SZ]; + struct polyhedron *poly; +} FACE; + +typedef struct polyhedron { + int numVerts, numFaces; + double verts[MAX_VERTS][3]; + FACE faces[MAX_FACES]; +} POLYHEDRON; + + +/* + ============================================================================ + globals + ============================================================================ +*/ + +static int A; /* alpha */ +static int B; /* beta */ +static int C; /* gamma */ + +/* projection integrals */ +static double P1, Pa, Pb, Paa, Pab, Pbb, Paaa, Paab, Pabb, Pbbb; + +/* face integrals */ +static double Fa, Fb, Fc, Faa, Fbb, Fcc, Faaa, Fbbb, Fccc, Faab, Fbbc, Fcca; + +/* volume integrals */ +static double T0, T1[3], T2[3], TP[3]; + + +/* + ============================================================================ + read in a polyhedron + ============================================================================ +*/ + +void readPolyhedron(char *name, POLYHEDRON *p) +{ + FILE *fp; + char line[200], *c; + int i, j, n; + double dx1, dy1, dz1, dx2, dy2, dz2, nx, ny, nz, len; + FACE *f; + + + if (!(fp = fopen(name, "r"))) { + printf("i/o error\n"); + exit(1); + } + + fscanf(fp, "%d", &p->numVerts); + printf("Reading in %d vertices\n", p->numVerts); + for (i = 0; i < p->numVerts; i++) + fscanf(fp, "%lf %lf %lf", + &p->verts[i][X], &p->verts[i][Y], &p->verts[i][Z]); + + fscanf(fp, "%d", &p->numFaces); + printf("Reading in %d faces\n", p->numFaces); + for (i = 0; i < p->numFaces; i++) { + f = &p->faces[i]; + f->poly = p; + fscanf(fp, "%d", &f->numVerts); + for (j = 0; j < f->numVerts; j++) fscanf(fp, "%d", &f->verts[j]); + + /* compute face normal and offset w from first 3 vertices */ + dx1 = p->verts[f->verts[1]][X] - p->verts[f->verts[0]][X]; + dy1 = p->verts[f->verts[1]][Y] - p->verts[f->verts[0]][Y]; + dz1 = p->verts[f->verts[1]][Z] - p->verts[f->verts[0]][Z]; + dx2 = p->verts[f->verts[2]][X] - p->verts[f->verts[1]][X]; + dy2 = p->verts[f->verts[2]][Y] - p->verts[f->verts[1]][Y]; + dz2 = p->verts[f->verts[2]][Z] - p->verts[f->verts[1]][Z]; + nx = dy1 * dz2 - dy2 * dz1; + ny = dz1 * dx2 - dz2 * dx1; + nz = dx1 * dy2 - dx2 * dy1; + len = sqrt(nx * nx + ny * ny + nz * nz); + f->norm[X] = nx / len; + f->norm[Y] = ny / len; + f->norm[Z] = nz / len; + f->w = - f->norm[X] * p->verts[f->verts[0]][X] + - f->norm[Y] * p->verts[f->verts[0]][Y] + - f->norm[Z] * p->verts[f->verts[0]][Z]; + + } + + fclose(fp); + +} + +/* + ============================================================================ + compute mass properties + ============================================================================ +*/ + + +/* compute various integrations over projection of face */ +void compProjectionIntegrals(FACE *f) +{ + double a0, a1, da; + double b0, b1, db; + double a0_2, a0_3, a0_4, b0_2, b0_3, b0_4; + double a1_2, a1_3, b1_2, b1_3; + double C1, Ca, Caa, Caaa, Cb, Cbb, Cbbb; + double Cab, Kab, Caab, Kaab, Cabb, Kabb; + int i; + + P1 = Pa = Pb = Paa = Pab = Pbb = Paaa = Paab = Pabb = Pbbb = 0.0; + + for (i = 0; i < f->numVerts; i++) { + a0 = f->poly->verts[f->verts[i]][A]; + b0 = f->poly->verts[f->verts[i]][B]; + a1 = f->poly->verts[f->verts[(i+1) % f->numVerts]][A]; + b1 = f->poly->verts[f->verts[(i+1) % f->numVerts]][B]; + da = a1 - a0; + db = b1 - b0; + a0_2 = a0 * a0; a0_3 = a0_2 * a0; a0_4 = a0_3 * a0; + b0_2 = b0 * b0; b0_3 = b0_2 * b0; b0_4 = b0_3 * b0; + a1_2 = a1 * a1; a1_3 = a1_2 * a1; + b1_2 = b1 * b1; b1_3 = b1_2 * b1; + + C1 = a1 + a0; + Ca = a1*C1 + a0_2; Caa = a1*Ca + a0_3; Caaa = a1*Caa + a0_4; + Cb = b1*(b1 + b0) + b0_2; Cbb = b1*Cb + b0_3; Cbbb = b1*Cbb + b0_4; + Cab = 3*a1_2 + 2*a1*a0 + a0_2; Kab = a1_2 + 2*a1*a0 + 3*a0_2; + Caab = a0*Cab + 4*a1_3; Kaab = a1*Kab + 4*a0_3; + Cabb = 4*b1_3 + 3*b1_2*b0 + 2*b1*b0_2 + b0_3; + Kabb = b1_3 + 2*b1_2*b0 + 3*b1*b0_2 + 4*b0_3; + + P1 += db*C1; + Pa += db*Ca; + Paa += db*Caa; + Paaa += db*Caaa; + Pb += da*Cb; + Pbb += da*Cbb; + Pbbb += da*Cbbb; + Pab += db*(b1*Cab + b0*Kab); + Paab += db*(b1*Caab + b0*Kaab); + Pabb += da*(a1*Cabb + a0*Kabb); + } + + P1 /= 2.0; + Pa /= 6.0; + Paa /= 12.0; + Paaa /= 20.0; + Pb /= -6.0; + Pbb /= -12.0; + Pbbb /= -20.0; + Pab /= 24.0; + Paab /= 60.0; + Pabb /= -60.0; +} + +compFaceIntegrals(FACE *f) +{ + double *n, w; + double k1, k2, k3, k4; + + compProjectionIntegrals(f); + + w = f->w; + n = f->norm; + k1 = 1 / n[C]; k2 = k1 * k1; k3 = k2 * k1; k4 = k3 * k1; + + Fa = k1 * Pa; + Fb = k1 * Pb; + Fc = -k2 * (n[A]*Pa + n[B]*Pb + w*P1); + + Faa = k1 * Paa; + Fbb = k1 * Pbb; + Fcc = k3 * (SQR(n[A])*Paa + 2*n[A]*n[B]*Pab + SQR(n[B])*Pbb + + w*(2*(n[A]*Pa + n[B]*Pb) + w*P1)); + + Faaa = k1 * Paaa; + Fbbb = k1 * Pbbb; + Fccc = -k4 * (CUBE(n[A])*Paaa + 3*SQR(n[A])*n[B]*Paab + + 3*n[A]*SQR(n[B])*Pabb + CUBE(n[B])*Pbbb + + 3*w*(SQR(n[A])*Paa + 2*n[A]*n[B]*Pab + SQR(n[B])*Pbb) + + w*w*(3*(n[A]*Pa + n[B]*Pb) + w*P1)); + + Faab = k1 * Paab; + Fbbc = -k2 * (n[A]*Pabb + n[B]*Pbbb + w*Pbb); + Fcca = k3 * (SQR(n[A])*Paaa + 2*n[A]*n[B]*Paab + SQR(n[B])*Pabb + + w*(2*(n[A]*Paa + n[B]*Pab) + w*Pa)); +} + +void compVolumeIntegrals(POLYHEDRON *p) +{ + FACE *f; + double nx, ny, nz; + int i; + + T0 = T1[X] = T1[Y] = T1[Z] + = T2[X] = T2[Y] = T2[Z] + = TP[X] = TP[Y] = TP[Z] = 0; + + for (i = 0; i < p->numFaces; i++) { + + f = &p->faces[i]; + + nx = fabs(f->norm[X]); + ny = fabs(f->norm[Y]); + nz = fabs(f->norm[Z]); + if (nx > ny && nx > nz) C = X; + else C = (ny > nz) ? Y : Z; + A = (C + 1) % 3; + B = (A + 1) % 3; + + compFaceIntegrals(f); + + T0 += f->norm[X] * ((A == X) ? Fa : ((B == X) ? Fb : Fc)); + + T1[A] += f->norm[A] * Faa; + T1[B] += f->norm[B] * Fbb; + T1[C] += f->norm[C] * Fcc; + T2[A] += f->norm[A] * Faaa; + T2[B] += f->norm[B] * Fbbb; + T2[C] += f->norm[C] * Fccc; + TP[A] += f->norm[A] * Faab; + TP[B] += f->norm[B] * Fbbc; + TP[C] += f->norm[C] * Fcca; + } + + T1[X] /= 2; T1[Y] /= 2; T1[Z] /= 2; + T2[X] /= 3; T2[Y] /= 3; T2[Z] /= 3; + TP[X] /= 2; TP[Y] /= 2; TP[Z] /= 2; +} + + +/* + ============================================================================ + main + ============================================================================ +*/ + + +int main(int argc, char *argv[]) +{ + POLYHEDRON p; + double density, mass; + double r[3]; /* center of mass */ + double J[3][3]; /* inertia tensor */ + + if (argc != 2) { + printf("usage: %s \n", argv[0]); + exit(0); + } + + readPolyhedron(argv[1], &p); + + compVolumeIntegrals(&p); + + + printf("\nT1 = %+20.6f\n\n", T0); + + printf("Tx = %+20.6f\n", T1[X]); + printf("Ty = %+20.6f\n", T1[Y]); + printf("Tz = %+20.6f\n\n", T1[Z]); + + printf("Txx = %+20.6f\n", T2[X]); + printf("Tyy = %+20.6f\n", T2[Y]); + printf("Tzz = %+20.6f\n\n", T2[Z]); + + printf("Txy = %+20.6f\n", TP[X]); + printf("Tyz = %+20.6f\n", TP[Y]); + printf("Tzx = %+20.6f\n\n", TP[Z]); + + density = 1.0; /* assume unit density */ + + mass = density * T0; + + /* compute center of mass */ + r[X] = T1[X] / T0; + r[Y] = T1[Y] / T0; + r[Z] = T1[Z] / T0; + + /* compute inertia tensor */ + J[X][X] = density * (T2[Y] + T2[Z]); + J[Y][Y] = density * (T2[Z] + T2[X]); + J[Z][Z] = density * (T2[X] + T2[Y]); + J[X][Y] = J[Y][X] = - density * TP[X]; + J[Y][Z] = J[Z][Y] = - density * TP[Y]; + J[Z][X] = J[X][Z] = - density * TP[Z]; + + /* translate inertia tensor to center of mass */ + J[X][X] -= mass * (r[Y]*r[Y] + r[Z]*r[Z]); + J[Y][Y] -= mass * (r[Z]*r[Z] + r[X]*r[X]); + J[Z][Z] -= mass * (r[X]*r[X] + r[Y]*r[Y]); + J[X][Y] = J[Y][X] += mass * r[X] * r[Y]; + J[Y][Z] = J[Z][Y] += mass * r[Y] * r[Z]; + J[Z][X] = J[X][Z] += mass * r[Z] * r[X]; + + printf("center of mass: (%+12.6f,%+12.6f,%+12.6f)\n\n", r[X], r[Y], r[Z]); + + printf("inertia tensor with origin at c.o.m. :\n"); + printf("%+15.6f %+15.6f %+15.6f\n", J[X][X], J[X][Y], J[X][Z]); + printf("%+15.6f %+15.6f %+15.6f\n", J[Y][X], J[Y][Y], J[Y][Z]); + printf("%+15.6f %+15.6f %+15.6f\n\n", J[Z][X], J[Z][Y], J[Z][Z]); + +} From f8147f5bb5c15263bce6c267785d504d673f4b42 Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Sat, 2 Jan 2010 13:01:37 +0100 Subject: [PATCH 002/250] Add basic scalar functions to calcEntry. --- applications/test/dictionary/Make/files | 1 + .../addToStaticMemberFunctionSelectionTable.H | 53 +++++ .../test/dictionary/calcEntry/calcEntry.C | 2 +- .../test/dictionary/calcEntry/calcEntry.H | 2 +- .../test/dictionary/calcEntry/calcEntry.atg | 205 +++++++++--------- .../dictionary/calcEntry/calcEntryInternal.C | 182 ++++++++++++++++ .../dictionary/calcEntry/calcEntryInternal.H | 101 +++++++++ .../dictionary/calcEntry/calcEntryParser.cpp | 111 +++++----- .../dictionary/calcEntry/calcEntryParser.h | 69 ++---- .../dictionary/calcEntry/calcEntryScanner.cpp | 52 ++--- .../dictionary/calcEntry/calcEntryScanner.h | 12 +- .../staticMemberFunctionSelectionTables.H | 147 +++++++++++++ applications/test/dictionary/testDictCalc | 8 +- 13 files changed, 704 insertions(+), 241 deletions(-) create mode 100644 applications/test/dictionary/calcEntry/addToStaticMemberFunctionSelectionTable.H create mode 100644 applications/test/dictionary/calcEntry/calcEntryInternal.C create mode 100644 applications/test/dictionary/calcEntry/calcEntryInternal.H create mode 100644 applications/test/dictionary/calcEntry/staticMemberFunctionSelectionTables.H diff --git a/applications/test/dictionary/Make/files b/applications/test/dictionary/Make/files index 148f5fb1c9..ff7a3caad4 100644 --- a/applications/test/dictionary/Make/files +++ b/applications/test/dictionary/Make/files @@ -1,6 +1,7 @@ dictionaryTest.C calcEntry/calcEntry.C +calcEntry/calcEntryInternal.C calcEntry/calcEntryParser.cpp calcEntry/calcEntryScanner.cpp diff --git a/applications/test/dictionary/calcEntry/addToStaticMemberFunctionSelectionTable.H b/applications/test/dictionary/calcEntry/addToStaticMemberFunctionSelectionTable.H new file mode 100644 index 0000000000..572f93ae23 --- /dev/null +++ b/applications/test/dictionary/calcEntry/addToStaticMemberFunctionSelectionTable.H @@ -0,0 +1,53 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +@file Foam::addToStaticMemberFunctionSelectionTable + +Description + Macros for easy insertion into member function selection tables + +\*---------------------------------------------------------------------------*/ + +#ifndef addToStaticMemberFunctionSelectionTable_H +#define addToStaticMemberFunctionSelectionTable_H + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + +// add to hash-table of functions with 'lookup' as the key +#define addNamedToStaticMemberFunctionSelectionTable\ +(baseType,thisType,memberFunction,argNames,lookup,functionPtr) \ + \ + /* Add the thisType memberFunction to the table, find by lookup name */ \ + baseType::add##memberFunction##argNames##StaticMemberFunctionToTable \ + add_##lookup##_##thisType##memberFunction##argNames##StaticMemberFunctionTo##baseType##Table_\ + (#lookup, functionPtr) + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + +#endif + +// ************************************************************************* // diff --git a/applications/test/dictionary/calcEntry/calcEntry.C b/applications/test/dictionary/calcEntry/calcEntry.C index 9810812308..7e634bc8b4 100644 --- a/applications/test/dictionary/calcEntry/calcEntry.C +++ b/applications/test/dictionary/calcEntry/calcEntry.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2009-2009 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2009-2010 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License diff --git a/applications/test/dictionary/calcEntry/calcEntry.H b/applications/test/dictionary/calcEntry/calcEntry.H index 027c4b510b..3db7562161 100644 --- a/applications/test/dictionary/calcEntry/calcEntry.H +++ b/applications/test/dictionary/calcEntry/calcEntry.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2009-2009 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2009-2010 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License diff --git a/applications/test/dictionary/calcEntry/calcEntry.atg b/applications/test/dictionary/calcEntry/calcEntry.atg index 90c0861143..57646c3cad 100644 --- a/applications/test/dictionary/calcEntry/calcEntry.atg +++ b/applications/test/dictionary/calcEntry/calcEntry.atg @@ -1,65 +1,72 @@ -/*------------------------------------------------------------------------- +/*---------------------------------*- C++ -*---------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2009-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +@file calcEntry.atg + +Description + An attributed Coco/R grammar to parse simple arithmetic expressions + +SourceFiles + generated + +\*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*\ compile with: Coco \ -frames $WM_THIRD_PARTY_DIR/coco-r \ calcEntry.atg --------------------------------------------------------------------------*/ +\*---------------------------------------------------------------------------*/ #include "dictionary.H" #include "scalar.H" #include "error.H" #include "wchar.H" +#include "DynamicList.H" +#include "calcEntryInternal.H" COMPILER calcEntry -$prefix=calcEntry -$namespace=Foam::functionEntries::calcEntryInternal -$eof=true // grammar handles eof itself + // grammar pragmas: + $prefix=calcEntry + $namespace=Foam::functionEntries::calcEntryInternal + $eof=true // grammar handles eof itself // Simple four function calculator for OpenFOAM dictionaries - //! with debug - static const int debug = 0; - - //! The parent dictionary +private: + //- The parent dictionary mutable dictionary* dict_; - //! Track that parent dictionary was set - bool hasDict_; - - //! The calculation result + //- The calculation result scalar val; - - //! token -> scalar - scalar getScalar() const - { - return coco_string_toDouble(t->val); - } - - //! token -> string - std::string getString() const - { - char* str = coco_string_create_char(t->val); - std::string s(str); - coco_string_delete(str); - return s; - } - - //! attach a dictionary - void dict(const dictionary& dict) - { - dict_ = const_cast(&dict); - hasDict_ = true; - } - - - //! lookup dictionary entry + //- lookup dictionary entry scalar getDictLookup() const { scalar dictValue = 0; - if (!hasDict_) + if (!dict_) { FatalErrorIn ( @@ -70,19 +77,14 @@ $eof=true // grammar handles eof itself return 0; } - char* chars = coco_string_create_char + char* str = coco_string_create_char ( t->val, 1, (coco_string_length(t->val) - 1) ); - word keyword(chars); - coco_string_delete(chars); - - if (debug) - { - Info<<"lookup: " << keyword << nl; - } + word keyword(str); + coco_string_delete(str); entry* entryPtr = dict_->lookupEntryPtr(keyword, true, false); if (entryPtr && !entryPtr->isDict()) @@ -107,23 +109,35 @@ $eof=true // grammar handles eof itself << exit(FatalError); } - return dictValue; } + +public: + + //- attach a dictionary + void dict(const dictionary& dict) + { + dict_ = const_cast(&dict); + } + + //- Return the calculated result scalar Result() const { return val; } +INITIALIZE + dict_ = 0; + val = 0; + /*---------------------------------------------------------------------------*/ CHARACTERS - letter = 'A'..'Z' + 'a'..'z'. - qualifier = '_' + ':'. - dollar = '$'. + letter = 'A'..'Z' + 'a'..'z' + '_'. digit = "0123456789". + alphanum = letter + digit. sign = '+' + '-'. cr = '\r'. lf = '\n'. @@ -138,16 +152,16 @@ TOKENS // identifier ident = - letter { letter | digit | qualifier }. + letter { alphanum }. // string string = '"' { stringCh | '\\' printable } '"'. // dictionary lookup identifier -// starts with '$' and otherwise limited to a normal indentifier +// starts with '$' and otherwise limited to a normal identifier variable = - dollar letter { letter | digit | qualifier }. + '$' letter { alphanum }. // floating point and integer numbers number = @@ -167,63 +181,35 @@ IGNORE cr + lf + tab PRODUCTIONS -calcEntry (. val = 0; - if (debug){Info<<"start val pos:"<< t->pos << nl;} - .) +calcEntry (. val = 0; .) = - '{' Expr '}' (. - if (debug){ - Info<<"end {} at pos:"<< t->pos - <<" val:"<< t->val - <<" len:"<< coco_string_length(t->val) - <<" la pos:"<< la->pos << nl; - } - // reposition to immediately after the closing '}' - scanner->buffer->SetPos - ( - t->pos + coco_string_length(t->val) - ); + '{' Expr '}' (. // reposition to immediately after the closing '}' + scanner->buffer->SetPos(t->pos + 1); .) - | ( Expr EOF ) + | ( Expr EOF ) . /*---------------------------------------------------------------------------*/ -Expr (. scalar val2 = 0; - if (debug) {Info<<"Expr:"<< val<< " pos:"<< t->pos << nl;} - .) +Expr (. scalar val2 = 0; .) = Term { - "+" Term (. if (debug) {Info<<"+Term:"<pos << nl;} - val += val2; - if (debug) {Info<<"="<< val<< " pos:"<< t->pos << nl;} - .) - | "-" Term (. if (debug) {Info<<"-Term:"<pos << nl;} - val -= val2; - if (debug) {Info<<"="<< val<< " pos:"<< t->pos << nl;} - .) + "+" Term (. val += val2; .) + | "-" Term (. val -= val2; .) } . /*---------------------------------------------------------------------------*/ -Term (. scalar val2 = 0; - if (debug) {Info<<"Term:"<< val<< " pos:"<< t->pos << nl;} - .) +Term (. scalar val2 = 0; .) = Factor { - "*" Factor (. if (debug) {Info<<"*Factor:"<pos << nl;} - val *= val2; - if (debug) {Info<<"="<< val<< " pos:"<< t->pos << nl;} - .) - | "/" Factor (. if (debug) {Info<<"/Factor:"<pos << nl;} - val /= val2; - if (debug) {Info<<"="<< val<< " pos:"<< t->pos << nl;} - .) + "*" Factor (. val *= val2; .) + | "/" Factor (. val /= val2; .) } . @@ -231,17 +217,32 @@ Term (. scalar val2 = 0; /*---------------------------------------------------------------------------*/ Factor = - variable (. val = getDictLookup(); - if (debug) {Info<<"lookup:"<pos << nl;} - .) - | number (. val = getScalar(); - if (debug) {Info<<"got num:"<pos << nl;} - .) - | '-' '(' Expr ')' (. val = -val; - if (debug) {Info<<"inv:"<pos << nl;} - .) - | '(' Expr ')' (. if (debug){Info<<"got Expr:"<pos << nl;} + Func + | variable (. val = getDictLookup(); .) + | number (. val = coco_string_toDouble(t->val); .) + | '-' '(' Expr ')' (. val = -val; .) + | '(' Expr ')' +. + + +/*---------------------------------------------------------------------------*/ + +// functions like sin(x) or pow(x, y) etc. +Func += + ident (. + char* str = coco_string_create_char(t->val); + word funcName(str); + coco_string_delete(str); + DynamicList param(4); // hold parameter values .) + '(' + [ (. scalar x; .) + Expr (. param.append(x); .) + { ',' Expr (. param.append(x); .) + } + ] + ')' (. val = scalarFunctions::dispatch(funcName, param); .) . diff --git a/applications/test/dictionary/calcEntry/calcEntryInternal.C b/applications/test/dictionary/calcEntry/calcEntryInternal.C new file mode 100644 index 0000000000..888475cee6 --- /dev/null +++ b/applications/test/dictionary/calcEntry/calcEntryInternal.C @@ -0,0 +1,182 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*---------------------------------------------------------------------------*/ + +#include "calcEntryInternal.H" +#include "addToMemberFunctionSelectionTable.H" +#include "addToStaticMemberFunctionSelectionTable.H" +#include "unitConversion.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace functionEntries +{ +namespace calcEntryInternal +{ + +defineStaticMemberFunctionSelectionTable(scalarFunctions,dispatch,ParamList); + + +scalar scalarFunctions::dispatch +( + const word& name, + const UList& param +) +{ + // create lookup name with parameter count + const word lookupName = name + '_' + Foam::name(param.size()); + + dispatchParamListMemberFunctionTable::iterator mfIter = + dispatchParamListMemberFunctionTablePtr_->find(lookupName); + + if (mfIter == dispatchParamListMemberFunctionTablePtr_->end()) + { + FatalErrorIn + ( + "calcEntryInternal::scalarFunctions::dispatch" + "(const word&, const UList&) : " + ) << "Unknown function " << name << nl << nl + << "Valid types are :" << endl + << dispatchParamListMemberFunctionTablePtr_->sortedToc() + << exit(FatalError); + } + + return mfIter()(param); +} + + +scalar scalarFunctions::pi_0(const UList& param) +{ + return constant::mathematical::pi; +} + +scalar scalarFunctions::degToRad_1(const UList& param) +{ + return degToRad(param[0]); +} + +scalar scalarFunctions::radToDeg_1(const UList& param) +{ + return radToDeg(param[0]); +} + +scalar scalarFunctions::sin_1(const UList& param) +{ + return Foam::sin(param[0]); +} + +scalar scalarFunctions::cos_1(const UList& param) +{ + return Foam::cos(param[0]); +} + +scalar scalarFunctions::pow_2(const UList& param) +{ + return Foam::pow(param[0], param[1]); +} + +scalar scalarFunctions::log_1(const UList& param) +{ + return Foam::log(param[0]); +} + +scalar scalarFunctions::log10_1(const UList& param) +{ + return Foam::log10(param[0]); +} + + + +addNamedToStaticMemberFunctionSelectionTable +( + scalarFunctions,scalarFunctions,dispatch,ParamList, + pi_0, + &scalarFunctions::pi_0 +); + +addNamedToStaticMemberFunctionSelectionTable +( + scalarFunctions,scalarFunctions,dispatch,ParamList, + degToRad_1, + &scalarFunctions::degToRad_1 +); + +addNamedToStaticMemberFunctionSelectionTable +( + scalarFunctions,scalarFunctions,dispatch,ParamList, + radToDeg_1, + &scalarFunctions::radToDeg_1 +); + +addNamedToStaticMemberFunctionSelectionTable +( + scalarFunctions,scalarFunctions,dispatch,ParamList, + sin_1, + &scalarFunctions::sin_1 +); + +addNamedToStaticMemberFunctionSelectionTable +( + scalarFunctions,scalarFunctions,dispatch,ParamList, + cos_1, + &scalarFunctions::cos_1 +); + +addNamedToStaticMemberFunctionSelectionTable +( + scalarFunctions,scalarFunctions,dispatch,ParamList, + pow_2, + &scalarFunctions::pow_2 +); + +addNamedToStaticMemberFunctionSelectionTable +( + scalarFunctions,scalarFunctions,dispatch,ParamList, + log_1, + &scalarFunctions::log_1 +); + + + +addNamedToStaticMemberFunctionSelectionTable +( + scalarFunctions,scalarFunctions,dispatch,ParamList, + log10_1, + &scalarFunctions::log10_1 +); + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace calcEntryInternal +} // End namespace functionEntries +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + +// ************************************************************************* // diff --git a/applications/test/dictionary/calcEntry/calcEntryInternal.H b/applications/test/dictionary/calcEntry/calcEntryInternal.H new file mode 100644 index 0000000000..73ff08c7e4 --- /dev/null +++ b/applications/test/dictionary/calcEntry/calcEntryInternal.H @@ -0,0 +1,101 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Namespace + Foam::functionEntries::calcEntryInternal + +Description + This dictionary function entry may or may not do anything particularly + useful - depending upon what is currently being used to test. + +SourceFiles + calcEntryInternal.C + +\*---------------------------------------------------------------------------*/ + +#ifndef calcEntryInternal_H +#define calcEntryInternal_H + +#include "functionEntry.H" +#include "memberFunctionSelectionTables.H" +#include "staticMemberFunctionSelectionTables.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace functionEntries +{ +namespace calcEntryInternal +{ + +/*---------------------------------------------------------------------------*\ + Class calcEntryFunctions Declaration +\*---------------------------------------------------------------------------*/ + +class scalarFunctions +{ +public: + + // Member Function Selectors + + declareStaticMemberFunctionSelectionTable + ( + scalar, + scalarFunctions, + dispatch, + ParamList, + ( + const UList& param + ), + (param) + ); + + //- Calculate + static scalar dispatch(const word&, const UList&); + + + static scalar pi_0(const UList&); + static scalar degToRad_1(const UList&); + static scalar radToDeg_1(const UList&); + static scalar cos_1(const UList&); + static scalar sin_1(const UList&); + static scalar pow_2(const UList&); + static scalar log_1(const UList&); + static scalar log10_1(const UList&); + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace calcEntryInternal +} // End namespace functionEntries +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/applications/test/dictionary/calcEntry/calcEntryParser.cpp b/applications/test/dictionary/calcEntry/calcEntryParser.cpp index 1ff95b8ac9..4fc4016207 100644 --- a/applications/test/dictionary/calcEntry/calcEntryParser.cpp +++ b/applications/test/dictionary/calcEntry/calcEntryParser.cpp @@ -91,105 +91,93 @@ bool Parser::WeakSeparator(int n, int syFol, int repFol) { void Parser::calcEntry() { - val = 0; - if (debug){Info<<"start val pos:"<< t->pos << nl;} - + val = 0; if (la->kind == 5) { Get(); Expr(val); Expect(6); - if (debug){ - Info<<"end {} at pos:"<< t->pos - <<" val:"<< t->val - <<" len:"<< coco_string_length(t->val) - <<" la pos:"<< la->pos << nl; - } - // reposition to immediately after the closing '}' - scanner->buffer->SetPos - ( - t->pos + coco_string_length(t->val) - ); + scanner->buffer->SetPos(t->pos + 1); } else if (StartOf(1)) { Expr(val); Expect(0); - } else SynErr(14); + } else SynErr(15); } void Parser::Expr(scalar& val) { - scalar val2 = 0; - if (debug) {Info<<"Expr:"<< val<< " pos:"<< t->pos << nl;} - + scalar val2 = 0; Term(val); while (la->kind == 7 || la->kind == 8) { if (la->kind == 7) { Get(); Term(val2); - if (debug) {Info<<"+Term:"<pos << nl;} - val += val2; - if (debug) {Info<<"="<< val<< " pos:"<< t->pos << nl;} - + val += val2; } else { Get(); Term(val2); - if (debug) {Info<<"-Term:"<pos << nl;} - val -= val2; - if (debug) {Info<<"="<< val<< " pos:"<< t->pos << nl;} - + val -= val2; } } } void Parser::Term(scalar& val) { - scalar val2 = 0; - if (debug) {Info<<"Term:"<< val<< " pos:"<< t->pos << nl;} - + scalar val2 = 0; Factor(val); while (la->kind == 9 || la->kind == 10) { if (la->kind == 9) { Get(); Factor(val2); - if (debug) {Info<<"*Factor:"<pos << nl;} - val *= val2; - if (debug) {Info<<"="<< val<< " pos:"<< t->pos << nl;} - + val *= val2; } else { Get(); Factor(val2); - if (debug) {Info<<"/Factor:"<pos << nl;} - val /= val2; - if (debug) {Info<<"="<< val<< " pos:"<< t->pos << nl;} - + val /= val2; } } } void Parser::Factor(scalar& val) { - if (la->kind == 3) { + if (la->kind == 1) { + Func(val); + } else if (la->kind == 3) { Get(); - val = getDictLookup(); - if (debug) {Info<<"lookup:"<pos << nl;} - + val = getDictLookup(); } else if (la->kind == 4) { Get(); - val = getScalar(); - if (debug) {Info<<"got num:"<pos << nl;} - + val = coco_string_toDouble(t->val); } else if (la->kind == 8) { Get(); Expect(11); Expr(val); Expect(12); - val = -val; - if (debug) {Info<<"inv:"<pos << nl;} - + val = -val; } else if (la->kind == 11) { Get(); Expr(val); Expect(12); - if (debug){Info<<"got Expr:"<pos << nl;} - - } else SynErr(15); + } else SynErr(16); +} + +void Parser::Func(scalar& val) { + Expect(1); + char* str = coco_string_create_char(t->val); + word funcName(str); + coco_string_delete(str); + DynamicList param(4); // hold parameter values + + Expect(11); + if (StartOf(1)) { + scalar x; + Expr(x); + param.append(x); + while (la->kind == 13) { + Get(); + Expr(x); + param.append(x); + } + } + Expect(12); + val = scalarFunctions::dispatch(funcName, param); } @@ -218,10 +206,16 @@ Parser::Parser(Scanner* scan, Errors* err) t(NULL), la(NULL) { - if (!errors) { // add in default error handling errors = new Errors(); } + // user-defined initialization: +dict_ = 0; + val = 0; + +/*---------------------------------------------------------------------------*/ + + } @@ -229,9 +223,9 @@ bool Parser::StartOf(int s) { const bool T = true; const bool x = false; - static bool set[2][15] = { - {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, - {x,x,x,T, T,x,x,x, T,x,x,T, x,x,x} + static const bool set[2][16] = { + {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x}, + {x,T,x,T, T,x,x,x, T,x,x,T, x,x,x,x} }; @@ -245,6 +239,8 @@ Parser::~Parser() { delete errors; } delete dummyToken; + // user-defined destruction: + } @@ -284,9 +280,10 @@ wchar_t* Errors::strerror(int n) case 10: s = coco_string_create(L"\"/\" expected"); break; case 11: s = coco_string_create(L"\"(\" expected"); break; case 12: s = coco_string_create(L"\")\" expected"); break; - case 13: s = coco_string_create(L"??? expected"); break; - case 14: s = coco_string_create(L"invalid calcEntry"); break; - case 15: s = coco_string_create(L"invalid Factor"); break; + case 13: s = coco_string_create(L"\",\" expected"); break; + case 14: s = coco_string_create(L"??? expected"); break; + case 15: s = coco_string_create(L"invalid calcEntry"); break; + case 16: s = coco_string_create(L"invalid Factor"); break; default: { diff --git a/applications/test/dictionary/calcEntry/calcEntryParser.h b/applications/test/dictionary/calcEntry/calcEntryParser.h index de12a3961e..afa25782a7 100644 --- a/applications/test/dictionary/calcEntry/calcEntryParser.h +++ b/applications/test/dictionary/calcEntry/calcEntryParser.h @@ -7,6 +7,8 @@ #include "scalar.H" #include "error.H" #include "wchar.H" +#include "DynamicList.H" +#include "calcEntryInternal.H" #include "calcEntryScanner.h" @@ -55,7 +57,7 @@ private: _variable=3, _number=4, }; - static const int maxT = 13; + static const int maxT = 14; static const int minErrDist = 2; //!< min. distance before reporting errors @@ -77,47 +79,19 @@ public: Token *t; //!< last recognized token Token *la; //!< lookahead token -static const int debug = 0; - - //! The parent dictionary +private: + //- The parent dictionary mutable dictionary* dict_; - //! Track that parent dictionary was set - bool hasDict_; - - //! The calculation result + //- The calculation result scalar val; - - //! token -> scalar - scalar getScalar() const - { - return coco_string_toDouble(t->val); - } - - //! token -> string - std::string getString() const - { - char* str = coco_string_create_char(t->val); - std::string s(str); - coco_string_delete(str); - return s; - } - - //! attach a dictionary - void dict(const dictionary& dict) - { - dict_ = const_cast(&dict); - hasDict_ = true; - } - - - //! lookup dictionary entry + //- lookup dictionary entry scalar getDictLookup() const { scalar dictValue = 0; - if (!hasDict_) + if (!dict_) { FatalErrorIn ( @@ -128,19 +102,14 @@ static const int debug = 0; return 0; } - char* chars = coco_string_create_char + char* str = coco_string_create_char ( t->val, 1, (coco_string_length(t->val) - 1) ); - word keyword(chars); - coco_string_delete(chars); - - if (debug) - { - Info<<"lookup: " << keyword << nl; - } + word keyword(str); + coco_string_delete(str); entry* entryPtr = dict_->lookupEntryPtr(keyword, true, false); if (entryPtr && !entryPtr->isDict()) @@ -165,18 +134,25 @@ static const int debug = 0; << exit(FatalError); } - return dictValue; } + +public: + + //- attach a dictionary + void dict(const dictionary& dict) + { + dict_ = const_cast(&dict); + } + + //- Return the calculated result scalar Result() const { return val; } -/*---------------------------------------------------------------------------*/ - //! Construct for the specified scanner @@ -185,13 +161,14 @@ static const int debug = 0; * handler, which will not be deleted upon destruction. */ Parser(Scanner* scan, Errors* err = 0); - ~Parser(); //!< Destructor - cleanup errors and dummyToken + ~Parser(); void SemErr(const wchar_t* msg); //!< Handle semantic error void calcEntry(); void Expr(scalar& val); void Term(scalar& val); void Factor(scalar& val); + void Func(scalar& val); void Parse(); //!< Execute the parse operation diff --git a/applications/test/dictionary/calcEntry/calcEntryScanner.cpp b/applications/test/dictionary/calcEntry/calcEntryScanner.cpp index b070bcf3f3..f475323086 100644 --- a/applications/test/dictionary/calcEntry/calcEntryScanner.cpp +++ b/applications/test/dictionary/calcEntry/calcEntryScanner.cpp @@ -21,7 +21,7 @@ namespace calcEntryInternal { // string handling, wide character wchar_t* coco_string_create(const wchar_t* str) { - int len = coco_string_length(str); + const int len = coco_string_length(str); wchar_t* dest = new wchar_t[len + 1]; if (len) { wcsncpy(dest, str, len); @@ -31,10 +31,7 @@ wchar_t* coco_string_create(const wchar_t* str) { } wchar_t* coco_string_create(const wchar_t* str, int index, int length) { - int len = coco_string_length(str); - if (len) { - len = length; - } + const int len = (str && *str) ? length : 0; wchar_t* dest = new wchar_t[len + 1]; if (len) { wcsncpy(dest, &(str[index]), len); @@ -69,8 +66,8 @@ wchar_t* coco_string_create_lower(const wchar_t* str, int index, int len) { wchar_t* coco_string_create_append(const wchar_t* str1, const wchar_t* str2) { - int str1Len = coco_string_length(str1); - int str2Len = coco_string_length(str2); + const int str1Len = coco_string_length(str1); + const int str2Len = coco_string_length(str2); wchar_t* dest = new wchar_t[str1Len + str2Len + 1]; @@ -82,7 +79,7 @@ wchar_t* coco_string_create_append(const wchar_t* str1, const wchar_t* str2) { } wchar_t* coco_string_create_append(const wchar_t* str1, const wchar_t ch) { - int len = coco_string_length(str1); + const int len = coco_string_length(str1); wchar_t* dest = new wchar_t[len + 2]; wcsncpy(dest, str1, len); // or use if (len) { wcscpy(dest, str1); } dest[len] = ch; @@ -100,8 +97,8 @@ int coco_string_length(const wchar_t* str) { } bool coco_string_endswith(const wchar_t* str, const wchar_t* endstr) { - int strLen = wcslen(str); - int endLen = wcslen(endstr); + const int strLen = wcslen(str); + const int endLen = wcslen(endstr); return (endLen <= strLen) && (wcscmp(str + strLen - endLen, endstr) == 0); } @@ -159,7 +156,7 @@ float coco_string_toFloat(const wchar_t* str) // wchar_t* coco_string_create(const char* str) { - int len = str ? strlen(str) : 0; + const int len = str ? strlen(str) : 0; wchar_t* dest = new wchar_t[len + 1]; for (int i = 0; i < len; ++i) { dest[i] = wchar_t(str[i]); @@ -169,7 +166,7 @@ wchar_t* coco_string_create(const char* str) { } wchar_t* coco_string_create(const char* str, int index, int length) { - int len = str ? length : 0; + const int len = str ? length : 0; wchar_t* dest = new wchar_t[len + 1]; for (int i = 0; i < len; ++i) { dest[i] = wchar_t(str[index + i]); @@ -180,8 +177,8 @@ wchar_t* coco_string_create(const char* str, int index, int length) { char* coco_string_create_char(const wchar_t* str) { - int len = coco_string_length(str); - char *dest = new char[len + 1]; + const int len = coco_string_length(str); + char* dest = new char[len + 1]; for (int i = 0; i < len; ++i) { dest[i] = char(str[i]); @@ -191,11 +188,8 @@ char* coco_string_create_char(const wchar_t* str) { } char* coco_string_create_char(const wchar_t* str, int index, int length) { - int len = coco_string_length(str); - if (len) { - len = length; - } - char *dest = new char[len + 1]; + const int len = (str && *str) ? length : 0; + char* dest = new char[len + 1]; for (int i = 0; i < len; ++i) { dest[i] = char(str[index + i]); } @@ -589,25 +583,29 @@ Scanner::~Scanner() { void Scanner::Init() { for (int i = 65; i <= 90; ++i) start.set(i, 1); + for (int i = 95; i <= 95; ++i) start.set(i, 1); for (int i = 97; i <= 122; ++i) start.set(i, 1); - for (int i = 36; i <= 36; ++i) start.set(i, 5); - start.set(45, 20); + start.set(45, 21); for (int i = 48; i <= 57; ++i) start.set(i, 9); start.set(34, 2); + start.set(36, 5); start.set(46, 7); start.set(123, 14); start.set(125, 15); - start.set(43, 21); + start.set(43, 22); start.set(42, 16); start.set(47, 17); start.set(40, 18); start.set(41, 19); + start.set(44, 20); start.set(Buffer::EoF, -1); tvalLength = 128; tval = new wchar_t[tvalLength]; // text of current token + tlen = 0; + tval[tlen] = 0; // HEAP_BLOCK_SIZE byte heap + pointer to next heap block heap = malloc(HEAP_BLOCK_SIZE + sizeof(void*)); @@ -813,7 +811,7 @@ Token* Scanner::NextToken() { case 0: { t->kind = noSym; break; } // NextCh already done case 1: case_1: - if ((ch >= L'0' && ch <= L':') || (ch >= L'A' && ch <= L'Z') || ch == L'_' || (ch >= L'a' && ch <= L'z')) {AddCh(); goto case_1;} + if ((ch >= L'0' && ch <= L'9') || (ch >= L'A' && ch <= L'Z') || ch == L'_' || (ch >= L'a' && ch <= L'z')) {AddCh(); goto case_1;} else {t->kind = 1; break;} case 2: case_2: @@ -829,11 +827,11 @@ Token* Scanner::NextToken() { case_4: {t->kind = 2; break;} case 5: - if ((ch >= L'A' && ch <= L'Z') || (ch >= L'a' && ch <= L'z')) {AddCh(); goto case_6;} + if ((ch >= L'A' && ch <= L'Z') || ch == L'_' || (ch >= L'a' && ch <= L'z')) {AddCh(); goto case_6;} else {t->kind = noSym; break;} case 6: case_6: - if ((ch >= L'0' && ch <= L':') || (ch >= L'A' && ch <= L'Z') || ch == L'_' || (ch >= L'a' && ch <= L'z')) {AddCh(); goto case_6;} + if ((ch >= L'0' && ch <= L'9') || (ch >= L'A' && ch <= L'Z') || ch == L'_' || (ch >= L'a' && ch <= L'z')) {AddCh(); goto case_6;} else {t->kind = 3; break;} case 7: case_7: @@ -880,9 +878,11 @@ Token* Scanner::NextToken() { case 19: {t->kind = 12; break;} case 20: + {t->kind = 13; break;} + case 21: if (ch == L'.') {AddCh(); goto case_7;} else {t->kind = 8; break;} - case 21: + case 22: if (ch == L'.') {AddCh(); goto case_7;} else {t->kind = 7; break;} diff --git a/applications/test/dictionary/calcEntry/calcEntryScanner.h b/applications/test/dictionary/calcEntry/calcEntryScanner.h index fdebddeebe..9ea17302c6 100644 --- a/applications/test/dictionary/calcEntry/calcEntryScanner.h +++ b/applications/test/dictionary/calcEntry/calcEntryScanner.h @@ -219,7 +219,6 @@ public: //------------------------------------------------------------------------------ //! maps characters (integers) to start states of tokens class StartStates { -private: class Elem { public: int key, val; @@ -235,7 +234,7 @@ public: StartStates() : tab(new Elem*[128]) { - memset(tab, 0, 128 * sizeof(Elem*)); + memset(tab, 0, 128*sizeof(Elem*)); } virtual ~StartStates() { @@ -252,7 +251,7 @@ public: void set(int key, int val) { Elem *e = new Elem(key, val); - int k = unsigned(key) % 128; + const int k = unsigned(key) % 128; e->next = tab[k]; tab[k] = e; } @@ -270,7 +269,6 @@ public: //------------------------------------------------------------------------------ //! maps strings to integers (identifiers to keyword kinds) class KeywordMap { -private: class Elem { public: wchar_t *key; @@ -290,7 +288,7 @@ public: KeywordMap() : tab(new Elem*[128]) { - memset(tab, 0, 128 * sizeof(Elem*)); + memset(tab, 0, 128*sizeof(Elem*)); } virtual ~KeywordMap() { @@ -323,8 +321,8 @@ public: //! A Coco/R Scanner class Scanner { private: - static const int maxT = 13; - static const int noSym = 13; + static const int maxT = 14; + static const int noSym = 14; static const int eofSym = 0; //!< end-of-file token id static const char EOL = '\n'; //!< end-of-line character diff --git a/applications/test/dictionary/calcEntry/staticMemberFunctionSelectionTables.H b/applications/test/dictionary/calcEntry/staticMemberFunctionSelectionTables.H new file mode 100644 index 0000000000..3febd71e8a --- /dev/null +++ b/applications/test/dictionary/calcEntry/staticMemberFunctionSelectionTables.H @@ -0,0 +1,147 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +@file Foam::staticMemberFunctionSelectionTables + +Description + Macros to enable the easy declaration of member function selection tables. + +\*---------------------------------------------------------------------------*/ + +#ifndef staticMemberFunctionSelectionTables_H +#define staticMemberFunctionSelectionTables_H + +#include "memberFunctionSelectionTables.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + +// external use: +// ~~~~~~~~~~~~~ +// declare a run-time selection: +#define declareStaticMemberFunctionSelectionTable\ +(returnType,baseType,memberFunction,argNames,argList,parList) \ + \ + /* Construct from argList function pointer type */ \ + typedef returnType (*memberFunction##argNames##MemberFunctionPtr)argList; \ + \ + /* Construct from argList function table type */ \ + typedef HashTable \ + \ + memberFunction##argNames##MemberFunctionTable; \ + \ + /* Construct from argList function pointer table pointer */ \ + static memberFunction##argNames##MemberFunctionTable* \ + memberFunction##argNames##MemberFunctionTablePtr_; \ + \ + /* Table memberFunction called from the table add function */ \ + static void construct##memberFunction##argNames##MemberFunctionTables(); \ + \ + /* Table destructor called from the table add function destructor */ \ + static void destroy##memberFunction##argNames##MemberFunctionTables(); \ + \ + /* Class to add constructor from argList to table */ \ + template \ + class add##memberFunction##argNames##StaticMemberFunctionToTable \ + { \ + public: \ + \ + add##memberFunction##argNames##StaticMemberFunctionToTable \ + ( \ + const word& lookup, \ + memberFunction##argNames##MemberFunctionPtr function \ + ) \ + { \ + construct##memberFunction##argNames##MemberFunctionTables(); \ + memberFunction##argNames##MemberFunctionTablePtr_->insert \ + ( \ + lookup, \ + function \ + ); \ + } \ + \ + ~add##memberFunction##argNames##StaticMemberFunctionToTable() \ + { \ + destroy##memberFunction##argNames##MemberFunctionTables(); \ + } \ + } + + +// internal use: +// constructor/destructor aid +#define defineStaticMemberFunctionSelectionTableConstructDestruct\ +(baseType,memberFunction,argNames) \ + \ + /* Table constructor called from the table add function constructor */ \ + void baseType::construct##memberFunction##argNames##MemberFunctionTables()\ + { \ + static bool constructed = false; \ + if (!constructed) \ + { \ + constructed = true; \ + baseType::memberFunction##argNames##MemberFunctionTablePtr_ \ + = new baseType::memberFunction##argNames##MemberFunctionTable;\ + } \ + }; \ + \ + /* Table destructor called from the table add function destructor */ \ + void baseType::destroy##memberFunction##argNames##MemberFunctionTables() \ + { \ + if (baseType::memberFunction##argNames##MemberFunctionTablePtr_) \ + { \ + delete baseType::memberFunction##argNames##MemberFunctionTablePtr_;\ + baseType::memberFunction##argNames##MemberFunctionTablePtr_ = NULL;\ + } \ + } + + +// internal use: +// create pointer to hash-table of functions +#define defineStaticMemberFunctionSelectionTablePtr\ +(baseType,memberFunction,argNames) \ + \ + /* Define the memberFunction table */ \ + baseType::memberFunction##argNames##MemberFunctionTable* \ + baseType::memberFunction##argNames##MemberFunctionTablePtr_ = NULL + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// external use: +// ~~~~~~~~~~~~~ +// define run-time selection table +#define defineStaticMemberFunctionSelectionTable\ +(baseType,memberFunction,argNames) \ + \ + defineStaticMemberFunctionSelectionTablePtr \ + (baseType,memberFunction,argNames); \ + defineStaticMemberFunctionSelectionTableConstructDestruct \ + (baseType,memberFunction,argNames) \ + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + +#endif + +// ************************************************************************* // diff --git a/applications/test/dictionary/testDictCalc b/applications/test/dictionary/testDictCalc index f1d67650e8..6f2c38a51c 100644 --- a/applications/test/dictionary/testDictCalc +++ b/applications/test/dictionary/testDictCalc @@ -37,7 +37,13 @@ p this calculation #calc{ is done inplace; -flowRate #calc{ $flowRatePerHour / 3600}; +flowRate #calc{ $flowRatePerHour / 3600 }; + +sin45 #calc{ sin( 45*pi() / 180 ) }; +cos45 #calc{ cos( degToRad(45) ) }; +pow #calc{ pow( $x, $y ) }; +log10 #calc{ log( 1e6 ) }; +// list #calc{ list() }; xxx yyy; foo 30; From cf91174880bb99ce96bdc1abdba5dcb22c6ad51b Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Sat, 2 Jan 2010 15:09:17 +0100 Subject: [PATCH 003/250] Use global lookup tables for the calcEntry scalar functions. Handle leading signs on functions etc. --- .../addToGlobalFunctionSelectionTable.H | 53 ++++++ .../test/dictionary/calcEntry/calcEntry.atg | 33 ++-- .../dictionary/calcEntry/calcEntryInternal.C | 171 ++++++------------ .../dictionary/calcEntry/calcEntryInternal.H | 54 ++---- .../dictionary/calcEntry/calcEntryParser.cpp | 28 +-- .../dictionary/calcEntry/calcEntryParser.h | 5 +- .../calcEntry/globalFunctionSelectionTables.H | 145 +++++++++++++++ applications/test/dictionary/testDictCalc | 7 +- 8 files changed, 314 insertions(+), 182 deletions(-) create mode 100644 applications/test/dictionary/calcEntry/addToGlobalFunctionSelectionTable.H create mode 100644 applications/test/dictionary/calcEntry/globalFunctionSelectionTables.H diff --git a/applications/test/dictionary/calcEntry/addToGlobalFunctionSelectionTable.H b/applications/test/dictionary/calcEntry/addToGlobalFunctionSelectionTable.H new file mode 100644 index 0000000000..d6eadfdd74 --- /dev/null +++ b/applications/test/dictionary/calcEntry/addToGlobalFunctionSelectionTable.H @@ -0,0 +1,53 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +@file Foam::addToGlobalFunctionSelectionTable + +Description + Macros for easy insertion into global function selection tables + +\*---------------------------------------------------------------------------*/ + +#ifndef addToGlobalFunctionSelectionTable_H +#define addToGlobalFunctionSelectionTable_H + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + +// add to hash-table of functions with 'lookup' as the key +#define addNamedToGlobalFunctionSelectionTable\ +(memberFunction,argNames,lookup,functionPtr) \ + \ + /* Add to the table, find by lookup name */ \ + add##memberFunction##argNames##GlobalMemberFunctionToTable \ + add_##lookup##_##memberFunction##argNames##GlobalMemberFunctionTo##Table_\ + (#lookup, functionPtr) + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + +#endif + +// ************************************************************************* // diff --git a/applications/test/dictionary/calcEntry/calcEntry.atg b/applications/test/dictionary/calcEntry/calcEntry.atg index 57646c3cad..ac6766aae4 100644 --- a/applications/test/dictionary/calcEntry/calcEntry.atg +++ b/applications/test/dictionary/calcEntry/calcEntry.atg @@ -39,10 +39,7 @@ SourceFiles \*---------------------------------------------------------------------------*/ #include "dictionary.H" -#include "scalar.H" -#include "error.H" #include "wchar.H" -#include "DynamicList.H" #include "calcEntryInternal.H" @@ -56,7 +53,7 @@ COMPILER calcEntry private: //- The parent dictionary - mutable dictionary* dict_; + dictionary* dict_; //- The calculation result scalar val; @@ -196,8 +193,8 @@ Expr (. scalar val2 = 0; .) = Term { - "+" Term (. val += val2; .) - | "-" Term (. val -= val2; .) + '+' Term (. val += val2; .) + | '-' Term (. val -= val2; .) } . @@ -208,20 +205,26 @@ Term (. scalar val2 = 0; .) = Factor { - "*" Factor (. val *= val2; .) - | "/" Factor (. val /= val2; .) + '*' Factor (. val *= val2; .) + | '/' Factor (. val /= val2; .) } . /*---------------------------------------------------------------------------*/ -Factor + +// Note the treatment of the leading signs is fairly generous +// eg, "10 + - 10" is treated like "10 + -10" +// +Factor (. bool negative = false; .) = - Func - | variable (. val = getDictLookup(); .) - | number (. val = coco_string_toDouble(t->val); .) - | '-' '(' Expr ')' (. val = -val; .) - | '(' Expr ')' + ['+' | '-' (. negative = true; .) + ] + ( + Func | '(' Expr ')' + | variable (. val = getDictLookup(); .) + | number (. val = coco_string_toDouble(t->val); .) + ) (. if (negative) { val = -val; } .) . @@ -242,7 +245,7 @@ Func { ',' Expr (. param.append(x); .) } ] - ')' (. val = scalarFunctions::dispatch(funcName, param); .) + ')' (. val = dispatch(funcName, param); .) . diff --git a/applications/test/dictionary/calcEntry/calcEntryInternal.C b/applications/test/dictionary/calcEntry/calcEntryInternal.C index 888475cee6..086238d9a3 100644 --- a/applications/test/dictionary/calcEntry/calcEntryInternal.C +++ b/applications/test/dictionary/calcEntry/calcEntryInternal.C @@ -25,8 +25,7 @@ License \*---------------------------------------------------------------------------*/ #include "calcEntryInternal.H" -#include "addToMemberFunctionSelectionTable.H" -#include "addToStaticMemberFunctionSelectionTable.H" +#include "addToGlobalFunctionSelectionTable.H" #include "unitConversion.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -38,14 +37,66 @@ namespace functionEntries namespace calcEntryInternal { -defineStaticMemberFunctionSelectionTable(scalarFunctions,dispatch,ParamList); +defineGlobalFunctionSelectionTable(dispatch,ParamList); -scalar scalarFunctions::dispatch -( - const word& name, - const UList& param -) +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#define globalConstant0(Name, Constant)\ +scalar Name##_0(const UList& param) \ +{ \ + return Constant; \ +} \ +addNamedToGlobalFunctionSelectionTable(dispatch,ParamList,Name##_0,&Name##_0) + + +#define globalFunction0(Name, Function)\ +scalar Name##_0(const UList& param) \ +{ \ + return Function(); \ +} \ +addNamedToGlobalFunctionSelectionTable(dispatch,ParamList,Name##_0,&Name##_0) + + +#define globalFunction1(Name, Function)\ +scalar Name##_1(const UList& param) \ +{ \ + return Function(param[0]); \ +} \ +addNamedToGlobalFunctionSelectionTable(dispatch,ParamList,Name##_1,&Name##_1) + + +#define globalFunction2(Name, Function)\ +scalar Name##_2(const UList& param) \ +{ \ + return Function(param[0], param[1]); \ +} \ +addNamedToGlobalFunctionSelectionTable(dispatch,ParamList,Name##_2,&Name##_2) + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +globalConstant0(pi, constant::mathematical::pi); + +globalFunction1(degToRad, degToRad); +globalFunction1(radToDeg, radToDeg); +globalFunction1(asin, Foam::asin); +globalFunction1(acos, Foam::acos); +globalFunction1(atan, Foam::atan); +globalFunction1(sin, Foam::sin); +globalFunction1(cos, Foam::cos); +globalFunction1(tan, Foam::tan); +globalFunction1(log, Foam::log); +globalFunction1(log10, Foam::log10); +globalFunction1(mag, Foam::mag); + +globalFunction2(atan2, Foam::atan2); +globalFunction2(pow, Foam::pow); + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +scalar dispatch(const word& name, const UList& param) { // create lookup name with parameter count const word lookupName = name + '_' + Foam::name(param.size()); @@ -69,114 +120,10 @@ scalar scalarFunctions::dispatch } -scalar scalarFunctions::pi_0(const UList& param) -{ - return constant::mathematical::pi; -} - -scalar scalarFunctions::degToRad_1(const UList& param) -{ - return degToRad(param[0]); -} - -scalar scalarFunctions::radToDeg_1(const UList& param) -{ - return radToDeg(param[0]); -} - -scalar scalarFunctions::sin_1(const UList& param) -{ - return Foam::sin(param[0]); -} - -scalar scalarFunctions::cos_1(const UList& param) -{ - return Foam::cos(param[0]); -} - -scalar scalarFunctions::pow_2(const UList& param) -{ - return Foam::pow(param[0], param[1]); -} - -scalar scalarFunctions::log_1(const UList& param) -{ - return Foam::log(param[0]); -} - -scalar scalarFunctions::log10_1(const UList& param) -{ - return Foam::log10(param[0]); -} - - - -addNamedToStaticMemberFunctionSelectionTable -( - scalarFunctions,scalarFunctions,dispatch,ParamList, - pi_0, - &scalarFunctions::pi_0 -); - -addNamedToStaticMemberFunctionSelectionTable -( - scalarFunctions,scalarFunctions,dispatch,ParamList, - degToRad_1, - &scalarFunctions::degToRad_1 -); - -addNamedToStaticMemberFunctionSelectionTable -( - scalarFunctions,scalarFunctions,dispatch,ParamList, - radToDeg_1, - &scalarFunctions::radToDeg_1 -); - -addNamedToStaticMemberFunctionSelectionTable -( - scalarFunctions,scalarFunctions,dispatch,ParamList, - sin_1, - &scalarFunctions::sin_1 -); - -addNamedToStaticMemberFunctionSelectionTable -( - scalarFunctions,scalarFunctions,dispatch,ParamList, - cos_1, - &scalarFunctions::cos_1 -); - -addNamedToStaticMemberFunctionSelectionTable -( - scalarFunctions,scalarFunctions,dispatch,ParamList, - pow_2, - &scalarFunctions::pow_2 -); - -addNamedToStaticMemberFunctionSelectionTable -( - scalarFunctions,scalarFunctions,dispatch,ParamList, - log_1, - &scalarFunctions::log_1 -); - - - -addNamedToStaticMemberFunctionSelectionTable -( - scalarFunctions,scalarFunctions,dispatch,ParamList, - log10_1, - &scalarFunctions::log10_1 -); - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // } // End namespace calcEntryInternal } // End namespace functionEntries } // End namespace Foam -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - - // ************************************************************************* // diff --git a/applications/test/dictionary/calcEntry/calcEntryInternal.H b/applications/test/dictionary/calcEntry/calcEntryInternal.H index 73ff08c7e4..2dd3a03056 100644 --- a/applications/test/dictionary/calcEntry/calcEntryInternal.H +++ b/applications/test/dictionary/calcEntry/calcEntryInternal.H @@ -26,8 +26,7 @@ Namespace Foam::functionEntries::calcEntryInternal Description - This dictionary function entry may or may not do anything particularly - useful - depending upon what is currently being used to test. + Contains global functions and classes for the calcEntry. SourceFiles calcEntryInternal.C @@ -37,9 +36,10 @@ SourceFiles #ifndef calcEntryInternal_H #define calcEntryInternal_H -#include "functionEntry.H" -#include "memberFunctionSelectionTables.H" -#include "staticMemberFunctionSelectionTables.H" +#include "error.H" +#include "scalar.H" +#include "DynamicList.H" +#include "globalFunctionSelectionTables.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -50,42 +50,22 @@ namespace functionEntries namespace calcEntryInternal { -/*---------------------------------------------------------------------------*\ - Class calcEntryFunctions Declaration -\*---------------------------------------------------------------------------*/ + // Global Function Selectors -class scalarFunctions -{ -public: - - // Member Function Selectors - - declareStaticMemberFunctionSelectionTable + declareGlobalFunctionSelectionTable + ( + scalar, + dispatch, + ParamList, ( - scalar, - scalarFunctions, - dispatch, - ParamList, - ( - const UList& param - ), - (param) - ); - - //- Calculate - static scalar dispatch(const word&, const UList&); + const UList& param + ), + (param) + ); - static scalar pi_0(const UList&); - static scalar degToRad_1(const UList&); - static scalar radToDeg_1(const UList&); - static scalar cos_1(const UList&); - static scalar sin_1(const UList&); - static scalar pow_2(const UList&); - static scalar log_1(const UList&); - static scalar log10_1(const UList&); - -}; + //- Dispatch calculation to the named function + scalar dispatch(const word&, const UList&); // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/applications/test/dictionary/calcEntry/calcEntryParser.cpp b/applications/test/dictionary/calcEntry/calcEntryParser.cpp index 4fc4016207..e1a3937823 100644 --- a/applications/test/dictionary/calcEntry/calcEntryParser.cpp +++ b/applications/test/dictionary/calcEntry/calcEntryParser.cpp @@ -137,25 +137,29 @@ void Parser::Term(scalar& val) { } void Parser::Factor(scalar& val) { + bool negative = false; + if (la->kind == 7 || la->kind == 8) { + if (la->kind == 7) { + Get(); + } else { + Get(); + negative = true; + } + } if (la->kind == 1) { Func(val); + } else if (la->kind == 11) { + Get(); + Expr(val); + Expect(12); } else if (la->kind == 3) { Get(); val = getDictLookup(); } else if (la->kind == 4) { Get(); val = coco_string_toDouble(t->val); - } else if (la->kind == 8) { - Get(); - Expect(11); - Expr(val); - Expect(12); - val = -val; - } else if (la->kind == 11) { - Get(); - Expr(val); - Expect(12); } else SynErr(16); + if (negative) { val = -val; } } void Parser::Func(scalar& val) { @@ -177,7 +181,7 @@ void Parser::Func(scalar& val) { } } Expect(12); - val = scalarFunctions::dispatch(funcName, param); + val = dispatch(funcName, param); } @@ -225,7 +229,7 @@ bool Parser::StartOf(int s) { static const bool set[2][16] = { {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x}, - {x,T,x,T, T,x,x,x, T,x,x,T, x,x,x,x} + {x,T,x,T, T,x,x,T, T,x,x,T, x,x,x,x} }; diff --git a/applications/test/dictionary/calcEntry/calcEntryParser.h b/applications/test/dictionary/calcEntry/calcEntryParser.h index afa25782a7..cfc036ccec 100644 --- a/applications/test/dictionary/calcEntry/calcEntryParser.h +++ b/applications/test/dictionary/calcEntry/calcEntryParser.h @@ -4,10 +4,7 @@ #define COCO_calcEntryPARSER_H__ #include "dictionary.H" -#include "scalar.H" -#include "error.H" #include "wchar.H" -#include "DynamicList.H" #include "calcEntryInternal.H" @@ -81,7 +78,7 @@ public: private: //- The parent dictionary - mutable dictionary* dict_; + dictionary* dict_; //- The calculation result scalar val; diff --git a/applications/test/dictionary/calcEntry/globalFunctionSelectionTables.H b/applications/test/dictionary/calcEntry/globalFunctionSelectionTables.H new file mode 100644 index 0000000000..4a7dfb4ac4 --- /dev/null +++ b/applications/test/dictionary/calcEntry/globalFunctionSelectionTables.H @@ -0,0 +1,145 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +@file Foam::globalFunctionSelectionTables + +Description + Macros to enable the easy declaration of global function selection tables. + +\*---------------------------------------------------------------------------*/ + +#ifndef globalMemberFunctionSelectionTables_H +#define globalMemberFunctionSelectionTables_H + +#include "memberFunctionSelectionTables.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + +// external use: +// ~~~~~~~~~~~~~ +// declare a run-time selection: +#define declareGlobalFunctionSelectionTable\ +(returnType,memberFunction,argNames,argList,parList) \ + \ + /* Construct from argList function pointer type */ \ + typedef returnType (*memberFunction##argNames##MemberFunctionPtr)argList; \ + \ + /* Construct from argList function table type */ \ + typedef HashTable \ + \ + memberFunction##argNames##MemberFunctionTable; \ + \ + /* Construct from argList function pointer table pointer */ \ + extern memberFunction##argNames##MemberFunctionTable* \ + memberFunction##argNames##MemberFunctionTablePtr_; \ + \ + /* Table memberFunction called from the table add function */ \ + void construct##memberFunction##argNames##MemberFunctionTables(); \ + \ + /* Table destructor called from the table add function destructor */ \ + void destroy##memberFunction##argNames##MemberFunctionTables(); \ + \ + /* Class to add constructor from argList to table */ \ + class add##memberFunction##argNames##GlobalMemberFunctionToTable \ + { \ + public: \ + \ + add##memberFunction##argNames##GlobalMemberFunctionToTable \ + ( \ + const word& lookup, \ + memberFunction##argNames##MemberFunctionPtr function \ + ) \ + { \ + construct##memberFunction##argNames##MemberFunctionTables(); \ + memberFunction##argNames##MemberFunctionTablePtr_->insert \ + ( \ + lookup, \ + function \ + ); \ + } \ + \ + ~add##memberFunction##argNames##GlobalMemberFunctionToTable() \ + { \ + destroy##memberFunction##argNames##MemberFunctionTables(); \ + } \ + } + +// internal use: +// constructor/destructor aid +#define defineGlobalFunctionSelectionTableConstructDestruct\ +(memberFunction,argNames) \ + \ + /* Table constructor called from the table add function */ \ + void construct##memberFunction##argNames##MemberFunctionTables()\ + { \ + static bool constructed = false; \ + if (!constructed) \ + { \ + constructed = true; \ + memberFunction##argNames##MemberFunctionTablePtr_ \ + = new memberFunction##argNames##MemberFunctionTable; \ + } \ + } \ + \ + /* Table destructor called from the table add function destructor */ \ + void destroy##memberFunction##argNames##MemberFunctionTables()\ + { \ + if (memberFunction##argNames##MemberFunctionTablePtr_) \ + { \ + delete memberFunction##argNames##MemberFunctionTablePtr_; \ + memberFunction##argNames##MemberFunctionTablePtr_ = NULL; \ + } \ + } + + +// internal use: +// create pointer to hash-table of functions +#define defineGlobalFunctionSelectionTablePtr\ +(memberFunction,argNames) \ + \ + /* Define the memberFunction table */ \ + memberFunction##argNames##MemberFunctionTable* \ + memberFunction##argNames##MemberFunctionTablePtr_ = NULL + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// external use: +// ~~~~~~~~~~~~~ +// define run-time selection table +#define defineGlobalFunctionSelectionTable\ +(memberFunction,argNames) \ + \ + defineGlobalFunctionSelectionTablePtr \ + (memberFunction,argNames); \ + defineGlobalFunctionSelectionTableConstructDestruct \ + (memberFunction,argNames) + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + +#endif + +// ************************************************************************* // diff --git a/applications/test/dictionary/testDictCalc b/applications/test/dictionary/testDictCalc index 6f2c38a51c..092a933a29 100644 --- a/applications/test/dictionary/testDictCalc +++ b/applications/test/dictionary/testDictCalc @@ -39,8 +39,11 @@ is done inplace; flowRate #calc{ $flowRatePerHour / 3600 }; -sin45 #calc{ sin( 45*pi() / 180 ) }; -cos45 #calc{ cos( degToRad(45) ) }; +// inplace redefine +flowRate #calc{ $flowRate * 0.1 }; + +sin45 #calc{ sin( 45.0 * pi() / 180 ) }; +cos45 #calc{ cos( degToRad(15- -15+ +15) ) }; pow #calc{ pow( $x, $y ) }; log10 #calc{ log( 1e6 ) }; // list #calc{ list() }; From d1a2be78724755441a53ef5b01cb71516acc44ce Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Sat, 2 Jan 2010 16:09:08 +0100 Subject: [PATCH 004/250] Reorganize runTimeSelection to include new macros from calcEntry. Added globalFunctionSelectionTables, staticMemberFunctionSelectionTables --- .../{ => construction}/addToRunTimeSelectionTable.H | 0 .../runTimeSelection/{ => construction}/runTimeSelectionTables.H | 0 .../globalFunctions}/addToGlobalFunctionSelectionTable.H | 0 .../globalFunctions}/globalFunctionSelectionTables.H | 0 .../memberFunctions}/addToMemberFunctionSelectionTable.H | 0 .../memberFunctions}/memberFunctionSelectionTables.H | 0 .../addToStaticMemberFunctionSelectionTable.H | 0 .../staticMemberFunctions}/staticMemberFunctionSelectionTables.H | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename src/OpenFOAM/db/runTimeSelection/{ => construction}/addToRunTimeSelectionTable.H (100%) rename src/OpenFOAM/db/runTimeSelection/{ => construction}/runTimeSelectionTables.H (100%) rename {applications/test/dictionary/calcEntry => src/OpenFOAM/db/runTimeSelection/globalFunctions}/addToGlobalFunctionSelectionTable.H (100%) rename {applications/test/dictionary/calcEntry => src/OpenFOAM/db/runTimeSelection/globalFunctions}/globalFunctionSelectionTables.H (100%) rename src/OpenFOAM/db/{memberFunctionSelection => runTimeSelection/memberFunctions}/addToMemberFunctionSelectionTable.H (100%) rename src/OpenFOAM/db/{memberFunctionSelection => runTimeSelection/memberFunctions}/memberFunctionSelectionTables.H (100%) rename {applications/test/dictionary/calcEntry => src/OpenFOAM/db/runTimeSelection/staticMemberFunctions}/addToStaticMemberFunctionSelectionTable.H (100%) rename {applications/test/dictionary/calcEntry => src/OpenFOAM/db/runTimeSelection/staticMemberFunctions}/staticMemberFunctionSelectionTables.H (100%) diff --git a/src/OpenFOAM/db/runTimeSelection/addToRunTimeSelectionTable.H b/src/OpenFOAM/db/runTimeSelection/construction/addToRunTimeSelectionTable.H similarity index 100% rename from src/OpenFOAM/db/runTimeSelection/addToRunTimeSelectionTable.H rename to src/OpenFOAM/db/runTimeSelection/construction/addToRunTimeSelectionTable.H diff --git a/src/OpenFOAM/db/runTimeSelection/runTimeSelectionTables.H b/src/OpenFOAM/db/runTimeSelection/construction/runTimeSelectionTables.H similarity index 100% rename from src/OpenFOAM/db/runTimeSelection/runTimeSelectionTables.H rename to src/OpenFOAM/db/runTimeSelection/construction/runTimeSelectionTables.H diff --git a/applications/test/dictionary/calcEntry/addToGlobalFunctionSelectionTable.H b/src/OpenFOAM/db/runTimeSelection/globalFunctions/addToGlobalFunctionSelectionTable.H similarity index 100% rename from applications/test/dictionary/calcEntry/addToGlobalFunctionSelectionTable.H rename to src/OpenFOAM/db/runTimeSelection/globalFunctions/addToGlobalFunctionSelectionTable.H diff --git a/applications/test/dictionary/calcEntry/globalFunctionSelectionTables.H b/src/OpenFOAM/db/runTimeSelection/globalFunctions/globalFunctionSelectionTables.H similarity index 100% rename from applications/test/dictionary/calcEntry/globalFunctionSelectionTables.H rename to src/OpenFOAM/db/runTimeSelection/globalFunctions/globalFunctionSelectionTables.H diff --git a/src/OpenFOAM/db/memberFunctionSelection/addToMemberFunctionSelectionTable.H b/src/OpenFOAM/db/runTimeSelection/memberFunctions/addToMemberFunctionSelectionTable.H similarity index 100% rename from src/OpenFOAM/db/memberFunctionSelection/addToMemberFunctionSelectionTable.H rename to src/OpenFOAM/db/runTimeSelection/memberFunctions/addToMemberFunctionSelectionTable.H diff --git a/src/OpenFOAM/db/memberFunctionSelection/memberFunctionSelectionTables.H b/src/OpenFOAM/db/runTimeSelection/memberFunctions/memberFunctionSelectionTables.H similarity index 100% rename from src/OpenFOAM/db/memberFunctionSelection/memberFunctionSelectionTables.H rename to src/OpenFOAM/db/runTimeSelection/memberFunctions/memberFunctionSelectionTables.H diff --git a/applications/test/dictionary/calcEntry/addToStaticMemberFunctionSelectionTable.H b/src/OpenFOAM/db/runTimeSelection/staticMemberFunctions/addToStaticMemberFunctionSelectionTable.H similarity index 100% rename from applications/test/dictionary/calcEntry/addToStaticMemberFunctionSelectionTable.H rename to src/OpenFOAM/db/runTimeSelection/staticMemberFunctions/addToStaticMemberFunctionSelectionTable.H diff --git a/applications/test/dictionary/calcEntry/staticMemberFunctionSelectionTables.H b/src/OpenFOAM/db/runTimeSelection/staticMemberFunctions/staticMemberFunctionSelectionTables.H similarity index 100% rename from applications/test/dictionary/calcEntry/staticMemberFunctionSelectionTables.H rename to src/OpenFOAM/db/runTimeSelection/staticMemberFunctions/staticMemberFunctionSelectionTables.H From ebfdafad7f0ed90ee990602888a224507311fb02 Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Sun, 3 Jan 2010 00:39:28 +0100 Subject: [PATCH 005/250] Add preliminary wmake rule for using CoCo/R. --- applications/test/dictionary/Allwmake | 11 +- applications/test/dictionary/Make/files | 5 +- applications/test/dictionary/Make/options | 2 + .../{calcEntry.atg => calcEntryParser.ATG} | 18 +- .../dictionary/calcEntry/calcEntryParser.cpp | 340 ------- .../dictionary/calcEntry/calcEntryParser.h | 180 ---- .../dictionary/calcEntry/calcEntryScanner.cpp | 932 ------------------ .../dictionary/calcEntry/calcEntryScanner.h | 396 -------- wmake/rules/General/coco | 6 + wmake/rules/General/standard | 1 + 10 files changed, 23 insertions(+), 1868 deletions(-) rename applications/test/dictionary/calcEntry/{calcEntry.atg => calcEntryParser.ATG} (95%) delete mode 100644 applications/test/dictionary/calcEntry/calcEntryParser.cpp delete mode 100644 applications/test/dictionary/calcEntry/calcEntryParser.h delete mode 100644 applications/test/dictionary/calcEntry/calcEntryScanner.cpp delete mode 100644 applications/test/dictionary/calcEntry/calcEntryScanner.h create mode 100644 wmake/rules/General/coco diff --git a/applications/test/dictionary/Allwmake b/applications/test/dictionary/Allwmake index fcf297dc89..86ec8fd45d 100755 --- a/applications/test/dictionary/Allwmake +++ b/applications/test/dictionary/Allwmake @@ -3,13 +3,8 @@ cd ${0%/*} || exit 1 # run from this directory # this will have to do until we have a makefile rule -if type Coco > /dev/null 2>&1 -then - Coco \ - -frames $WM_THIRD_PARTY_DIR/coco-r \ - calcEntry/calcEntry.atg -else - echo "Coco not installed" -fi +type Coco > /dev/null 2>&1 || { + echo "Coco not installed -- cannot make this test" +} wmake diff --git a/applications/test/dictionary/Make/files b/applications/test/dictionary/Make/files index ff7a3caad4..89d95d0298 100644 --- a/applications/test/dictionary/Make/files +++ b/applications/test/dictionary/Make/files @@ -1,8 +1,7 @@ dictionaryTest.C -calcEntry/calcEntry.C +calcEntry/calcEntryParser.ATG calcEntry/calcEntryInternal.C -calcEntry/calcEntryParser.cpp -calcEntry/calcEntryScanner.cpp +calcEntry/calcEntry.C EXE = $(FOAM_USER_APPBIN)/dictionaryTest diff --git a/applications/test/dictionary/Make/options b/applications/test/dictionary/Make/options index e69de29bb2..3af3c946ac 100644 --- a/applications/test/dictionary/Make/options +++ b/applications/test/dictionary/Make/options @@ -0,0 +1,2 @@ +EXE_INC = -IcalcEntry -I$(OBJECTS_DIR) + diff --git a/applications/test/dictionary/calcEntry/calcEntry.atg b/applications/test/dictionary/calcEntry/calcEntryParser.ATG similarity index 95% rename from applications/test/dictionary/calcEntry/calcEntry.atg rename to applications/test/dictionary/calcEntry/calcEntryParser.ATG index ac6766aae4..e1a1567700 100644 --- a/applications/test/dictionary/calcEntry/calcEntry.atg +++ b/applications/test/dictionary/calcEntry/calcEntryParser.ATG @@ -22,7 +22,7 @@ License along with OpenFOAM; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -@file calcEntry.atg +@file calcEntryParser.ATG Description An attributed Coco/R grammar to parse simple arithmetic expressions @@ -34,8 +34,8 @@ SourceFiles /*---------------------------------------------------------------------------*\ compile with: Coco \ - -frames $WM_THIRD_PARTY_DIR/coco-r \ - calcEntry.atg + [-single] -frames $WM_THIRD_PARTY_DIR/coco-r \ + calcEntryParser.ATG \*---------------------------------------------------------------------------*/ #include "dictionary.H" @@ -61,8 +61,6 @@ private: //- lookup dictionary entry scalar getDictLookup() const { - scalar dictValue = 0; - if (!dict_) { FatalErrorIn @@ -83,6 +81,8 @@ private: word keyword(str); coco_string_delete(str); + scalar dictValue = 0; + entry* entryPtr = dict_->lookupEntryPtr(keyword, true, false); if (entryPtr && !entryPtr->isDict()) { @@ -237,15 +237,15 @@ Func char* str = coco_string_create_char(t->val); word funcName(str); coco_string_delete(str); - DynamicList param(4); // hold parameter values + DynamicList stack(4); .) '(' [ (. scalar x; .) - Expr (. param.append(x); .) - { ',' Expr (. param.append(x); .) + Expr (. stack.append(x); .) + { ',' Expr (. stack.append(x); .) } ] - ')' (. val = dispatch(funcName, param); .) + ')' (. val = dispatch(funcName, stack); .) . diff --git a/applications/test/dictionary/calcEntry/calcEntryParser.cpp b/applications/test/dictionary/calcEntry/calcEntryParser.cpp deleted file mode 100644 index e1a3937823..0000000000 --- a/applications/test/dictionary/calcEntry/calcEntryParser.cpp +++ /dev/null @@ -1,340 +0,0 @@ - - -#include -#include "calcEntryParser.h" - - -namespace Foam { -namespace functionEntries { -namespace calcEntryInternal { - - -// ---------------------------------------------------------------------------- -// Parser Implementation -// ---------------------------------------------------------------------------- - -void Parser::SynErr(int n) { - if (errDist >= minErrDist) errors->SynErr(la->line, la->col, n); - errDist = 0; -} - - -void Parser::SemErr(const wchar_t* msg) { - if (errDist >= minErrDist) errors->Error(t->line, t->col, msg); - errDist = 0; -} - - -void Parser::Get() { - for (;;) { - t = la; - la = scanner->Scan(); - if (la->kind <= maxT) { - ++errDist; - break; - } - - if (dummyToken != t) { - dummyToken->kind = t->kind; - dummyToken->pos = t->pos; - dummyToken->col = t->col; - dummyToken->line = t->line; - dummyToken->next = NULL; - coco_string_delete(dummyToken->val); - dummyToken->val = coco_string_create(t->val); - t = dummyToken; - } - la = t; - } -} - - -void Parser::Expect(int n) { - if (la->kind == n) { - Get(); - } - else { - SynErr(n); - } -} - - -void Parser::ExpectWeak(int n, int follow) { - if (la->kind == n) { - Get(); - } - else { - SynErr(n); - while (!StartOf(follow)) { - Get(); - } - } -} - - -bool Parser::WeakSeparator(int n, int syFol, int repFol) { - if (la->kind == n) { - Get(); - return true; - } - else if (StartOf(repFol)) { - return false; - } - else { - SynErr(n); - while (!(StartOf(syFol) || StartOf(repFol) || StartOf(0))) { - Get(); - } - return StartOf(syFol); - } -} - - -void Parser::calcEntry() { - val = 0; - if (la->kind == 5) { - Get(); - Expr(val); - Expect(6); - scanner->buffer->SetPos(t->pos + 1); - - } else if (StartOf(1)) { - Expr(val); - Expect(0); - } else SynErr(15); -} - -void Parser::Expr(scalar& val) { - scalar val2 = 0; - Term(val); - while (la->kind == 7 || la->kind == 8) { - if (la->kind == 7) { - Get(); - Term(val2); - val += val2; - } else { - Get(); - Term(val2); - val -= val2; - } - } -} - -void Parser::Term(scalar& val) { - scalar val2 = 0; - Factor(val); - while (la->kind == 9 || la->kind == 10) { - if (la->kind == 9) { - Get(); - Factor(val2); - val *= val2; - } else { - Get(); - Factor(val2); - val /= val2; - } - } -} - -void Parser::Factor(scalar& val) { - bool negative = false; - if (la->kind == 7 || la->kind == 8) { - if (la->kind == 7) { - Get(); - } else { - Get(); - negative = true; - } - } - if (la->kind == 1) { - Func(val); - } else if (la->kind == 11) { - Get(); - Expr(val); - Expect(12); - } else if (la->kind == 3) { - Get(); - val = getDictLookup(); - } else if (la->kind == 4) { - Get(); - val = coco_string_toDouble(t->val); - } else SynErr(16); - if (negative) { val = -val; } -} - -void Parser::Func(scalar& val) { - Expect(1); - char* str = coco_string_create_char(t->val); - word funcName(str); - coco_string_delete(str); - DynamicList param(4); // hold parameter values - - Expect(11); - if (StartOf(1)) { - scalar x; - Expr(x); - param.append(x); - while (la->kind == 13) { - Get(); - Expr(x); - param.append(x); - } - } - Expect(12); - val = dispatch(funcName, param); -} - - - -void Parser::Parse() { - t = NULL; - if (dummyToken) { // safety: someone might call Parse() twice - delete dummyToken; - } - la = dummyToken = new Token(); - la->val = coco_string_create(L"Dummy Token"); - Get(); - calcEntry(); - // let grammar deal with end-of-file expectations - -} - - -Parser::Parser(Scanner* scan, Errors* err) -: - dummyToken(NULL), - deleteErrorsDestruct_(!err), - errDist(minErrDist), - scanner(scan), - errors(err), - t(NULL), - la(NULL) -{ - if (!errors) { // add in default error handling - errors = new Errors(); - } - // user-defined initialization: -dict_ = 0; - val = 0; - -/*---------------------------------------------------------------------------*/ - - -} - - -bool Parser::StartOf(int s) { - const bool T = true; - const bool x = false; - - static const bool set[2][16] = { - {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x}, - {x,T,x,T, T,x,x,T, T,x,x,T, x,x,x,x} - }; - - - - return set[s][la->kind]; -} - - -Parser::~Parser() { - if (deleteErrorsDestruct_) { // delete default error handling - delete errors; - } - delete dummyToken; - // user-defined destruction: - -} - - -// ---------------------------------------------------------------------------- -// Errors Implementation -// ---------------------------------------------------------------------------- - -Errors::Errors() -: - count(0) -{} - - -Errors::~Errors() -{} - - -void Errors::clear() { - count = 0; -} - - -wchar_t* Errors::strerror(int n) -{ - wchar_t* s; - switch (n) { - case 0: s = coco_string_create(L"EOF expected"); break; - case 1: s = coco_string_create(L"ident expected"); break; - case 2: s = coco_string_create(L"string expected"); break; - case 3: s = coco_string_create(L"variable expected"); break; - case 4: s = coco_string_create(L"number expected"); break; - case 5: s = coco_string_create(L"\"{\" expected"); break; - case 6: s = coco_string_create(L"\"}\" expected"); break; - case 7: s = coco_string_create(L"\"+\" expected"); break; - case 8: s = coco_string_create(L"\"-\" expected"); break; - case 9: s = coco_string_create(L"\"*\" expected"); break; - case 10: s = coco_string_create(L"\"/\" expected"); break; - case 11: s = coco_string_create(L"\"(\" expected"); break; - case 12: s = coco_string_create(L"\")\" expected"); break; - case 13: s = coco_string_create(L"\",\" expected"); break; - case 14: s = coco_string_create(L"??? expected"); break; - case 15: s = coco_string_create(L"invalid calcEntry"); break; - case 16: s = coco_string_create(L"invalid Factor"); break; - - default: - { - wchar_t format[20]; - coco_swprintf(format, 20, L"error %d", n); - s = coco_string_create(format); - } - break; - } - return s; -} - - -void Errors::Warning(const wchar_t* msg) { - wprintf(L"%ls\n", msg); -} - - -void Errors::Warning(int line, int col, const wchar_t* msg) { - wprintf(L"-- line %d col %d: %ls\n", line, col, msg); -} - - -void Errors::Error(int line, int col, const wchar_t* msg) { - wprintf(L"-- line %d col %d: %ls\n", line, col, msg); - count++; -} - - -void Errors::SynErr(int line, int col, int n) { - wchar_t* msg = this->strerror(n); - this->Error(line, col, msg); - coco_string_delete(msg); -} - - -void Errors::Exception(const wchar_t* msg) { - wprintf(L"%ls", msg); - ::exit(1); -} - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -} // namespace -} // namespace -} // namespace - - -// ************************************************************************* // diff --git a/applications/test/dictionary/calcEntry/calcEntryParser.h b/applications/test/dictionary/calcEntry/calcEntryParser.h deleted file mode 100644 index cfc036ccec..0000000000 --- a/applications/test/dictionary/calcEntry/calcEntryParser.h +++ /dev/null @@ -1,180 +0,0 @@ - - -#ifndef COCO_calcEntryPARSER_H__ -#define COCO_calcEntryPARSER_H__ - -#include "dictionary.H" -#include "wchar.H" -#include "calcEntryInternal.H" - - -#include "calcEntryScanner.h" - -namespace Foam { -namespace functionEntries { -namespace calcEntryInternal { - - -//! Parser error handing -class Errors { -public: - int count; //!< The number of errors detected - - //! Allocate and return a string describing the given error code. - /** It is the responsibility of the caller to free this string, - * eg, with coco_string_delete() - */ - static wchar_t* strerror(int n); - - Errors(); //!< Construct null - start with no errors - virtual ~Errors(); //!< Destructor - virtual void clear(); //!< Clear the error count - - //! Handle a general warning 'msg' - virtual void Warning(const wchar_t* msg); - //! Handle a general warning 'msg' - virtual void Warning(int line, int col, const wchar_t* msg); - //! Handle general error 'msg' (eg, a semantic error) - virtual void Error(int line, int col, const wchar_t* msg); - //! Handle syntax error 'n', uses strerror for the message, calls Error() - virtual void SynErr(int line, int col, int n); - //! Handle a general exception 'msg' - virtual void Exception(const wchar_t* msg); - -}; // Errors - - -//! A Coco/R Parser -class Parser { -private: - enum { - _EOF=0, - _ident=1, - _string=2, - _variable=3, - _number=4, - }; - static const int maxT = 14; - - static const int minErrDist = 2; //!< min. distance before reporting errors - - Token *dummyToken; - bool deleteErrorsDestruct_; //!< delete the 'errors' member in destructor - int errDist; - - void SynErr(int n); //!< Handle syntax error 'n' - void Get(); - void Expect(int n); - bool StartOf(int s); - void ExpectWeak(int n, int follow); - bool WeakSeparator(int n, int syFol, int repFol); - -public: - Scanner *scanner; - Errors *errors; - - Token *t; //!< last recognized token - Token *la; //!< lookahead token - -private: - //- The parent dictionary - dictionary* dict_; - - //- The calculation result - scalar val; - - //- lookup dictionary entry - scalar getDictLookup() const - { - scalar dictValue = 0; - - if (!dict_) - { - FatalErrorIn - ( - "calcEntry::getDictEntry() const" - ) << "No dictionary attached!" - << exit(FatalError); - - return 0; - } - - char* str = coco_string_create_char - ( - t->val, - 1, - (coco_string_length(t->val) - 1) - ); - word keyword(str); - coco_string_delete(str); - - entry* entryPtr = dict_->lookupEntryPtr(keyword, true, false); - if (entryPtr && !entryPtr->isDict()) - { - if (entryPtr->stream().size() != 1) - { - FatalErrorIn - ( - "calcEntry::getDictEntry() const" - ) << "keyword " << keyword << " has " - << entryPtr->stream().size() << " values in dictionary " - << exit(FatalError); - } - entryPtr->stream() >> dictValue; - } - else - { - FatalErrorIn - ( - "calcEntry::getDictEntry() const" - ) << "keyword " << keyword << " is undefined in dictionary " - << exit(FatalError); - } - - return dictValue; - } - - -public: - - //- attach a dictionary - void dict(const dictionary& dict) - { - dict_ = const_cast(&dict); - } - - //- Return the calculated result - scalar Result() const - { - return val; - } - - - - - //! Construct for the specified scanner - /** - * Use the default error handling, or optionally provide an error - * handler, which will not be deleted upon destruction. - */ - Parser(Scanner* scan, Errors* err = 0); - ~Parser(); - void SemErr(const wchar_t* msg); //!< Handle semantic error - - void calcEntry(); - void Expr(scalar& val); - void Term(scalar& val); - void Factor(scalar& val); - void Func(scalar& val); - - void Parse(); //!< Execute the parse operation - -}; // end Parser - -} // namespace -} // namespace -} // namespace - - -#endif // COCO_calcEntryPARSER_H__ - diff --git a/applications/test/dictionary/calcEntry/calcEntryScanner.cpp b/applications/test/dictionary/calcEntry/calcEntryScanner.cpp deleted file mode 100644 index f475323086..0000000000 --- a/applications/test/dictionary/calcEntry/calcEntryScanner.cpp +++ /dev/null @@ -1,932 +0,0 @@ - - -#include - -#include "calcEntryScanner.h" - -// values for the file stream buffering -#define MIN_BUFFER_LENGTH 1024 // 1KB -#define MAX_BUFFER_LENGTH (64*MIN_BUFFER_LENGTH) // 64KB -// value for the heap management -#define HEAP_BLOCK_SIZE (64*1024) // 64KB - - -namespace Foam { -namespace functionEntries { -namespace calcEntryInternal { - - -// * * * * * * * * * * Wide Character String Routines * * * * * * * * * * * // - -// string handling, wide character - -wchar_t* coco_string_create(const wchar_t* str) { - const int len = coco_string_length(str); - wchar_t* dest = new wchar_t[len + 1]; - if (len) { - wcsncpy(dest, str, len); - } - dest[len] = 0; - return dest; -} - -wchar_t* coco_string_create(const wchar_t* str, int index, int length) { - const int len = (str && *str) ? length : 0; - wchar_t* dest = new wchar_t[len + 1]; - if (len) { - wcsncpy(dest, &(str[index]), len); - } - dest[len] = 0; - return dest; -} - - -wchar_t* coco_string_create_lower(const wchar_t* str) { - if (!str) { return NULL; } - return coco_string_create_lower(str, 0, wcslen(str)); -} - - -wchar_t* coco_string_create_lower(const wchar_t* str, int index, int len) { - if (!str) { return NULL; } - wchar_t* dest = new wchar_t[len + 1]; - - for (int i = 0; i < len; i++) { - const wchar_t ch = str[index + i]; - if ((L'A' <= ch) && (ch <= L'Z')) { - dest[i] = ch - (L'A' - L'a'); - } - else { - dest[i] = ch; - } - } - dest[len] = L'\0'; - return dest; -} - - -wchar_t* coco_string_create_append(const wchar_t* str1, const wchar_t* str2) { - const int str1Len = coco_string_length(str1); - const int str2Len = coco_string_length(str2); - - wchar_t* dest = new wchar_t[str1Len + str2Len + 1]; - - if (str1Len) { wcscpy(dest, str1); } - if (str2Len) { wcscpy(dest + str1Len, str2); } - - dest[str1Len + str2Len] = 0; - return dest; -} - -wchar_t* coco_string_create_append(const wchar_t* str1, const wchar_t ch) { - const int len = coco_string_length(str1); - wchar_t* dest = new wchar_t[len + 2]; - wcsncpy(dest, str1, len); // or use if (len) { wcscpy(dest, str1); } - dest[len] = ch; - dest[len + 1] = 0; - return dest; -} - -void coco_string_delete(wchar_t* &str) { - delete [] str; - str = NULL; -} - -int coco_string_length(const wchar_t* str) { - return str ? wcslen(str) : 0; -} - -bool coco_string_endswith(const wchar_t* str, const wchar_t* endstr) { - const int strLen = wcslen(str); - const int endLen = wcslen(endstr); - return (endLen <= strLen) && (wcscmp(str + strLen - endLen, endstr) == 0); -} - -int coco_string_indexof(const wchar_t* str, const wchar_t ch) { - const wchar_t* fnd = wcschr(str, ch); - return fnd ? (fnd - str) : -1; -} - -int coco_string_lastindexof(const wchar_t* str, const wchar_t ch) { - const wchar_t* fnd = wcsrchr(str, ch); - return fnd ? (fnd - str) : -1; -} - -void coco_string_merge(wchar_t* &dest, const wchar_t* str) { - if (!str) { return; } - wchar_t* newstr = coco_string_create_append(dest, str); - delete [] dest; - dest = newstr; -} - -bool coco_string_equal(const wchar_t* str1, const wchar_t* str2) { - return wcscmp(str1, str2) == 0; -} - -int coco_string_compareto(const wchar_t* str1, const wchar_t* str2) { - return wcscmp(str1, str2); -} - -int coco_string_hash(const wchar_t* str) { - int h = 0; - if (!str) { return 0; } - while (*str != 0) { - h = (h * 7) ^ *str; - ++str; - } - if (h < 0) { h = -h; } - return h; -} - - -double coco_string_toDouble(const wchar_t* str) -{ - return str ? wcstod(str, NULL) : 0; -} - -float coco_string_toFloat(const wchar_t* str) -{ - return str ? wcstof(str, NULL) : 0; -} - - - -// -// string handling, byte character -// - -wchar_t* coco_string_create(const char* str) { - const int len = str ? strlen(str) : 0; - wchar_t* dest = new wchar_t[len + 1]; - for (int i = 0; i < len; ++i) { - dest[i] = wchar_t(str[i]); - } - dest[len] = 0; - return dest; -} - -wchar_t* coco_string_create(const char* str, int index, int length) { - const int len = str ? length : 0; - wchar_t* dest = new wchar_t[len + 1]; - for (int i = 0; i < len; ++i) { - dest[i] = wchar_t(str[index + i]); - } - dest[len] = 0; - return dest; -} - - -char* coco_string_create_char(const wchar_t* str) { - const int len = coco_string_length(str); - char* dest = new char[len + 1]; - for (int i = 0; i < len; ++i) - { - dest[i] = char(str[i]); - } - dest[len] = 0; - return dest; -} - -char* coco_string_create_char(const wchar_t* str, int index, int length) { - const int len = (str && *str) ? length : 0; - char* dest = new char[len + 1]; - for (int i = 0; i < len; ++i) { - dest[i] = char(str[index + i]); - } - dest[len] = 0; - return dest; -} - - -void coco_string_delete(char* &str) { - delete [] str; - str = NULL; -} - - -double coco_string_toDouble(const char* str) -{ - return str ? strtod(str, NULL) : 0; -} - -float coco_string_toFloat(const char* str) -{ - return str ? strtof(str, NULL) : 0; -} - - -// * * * * * * * * * End of Wide Character String Routines * * * * * * * * * // - - -Token::Token() -: - kind(0), - pos(0), - col(0), - line(0), - val(NULL), - next(NULL) -{} - - -// Note: this delete may not be correct if the token was actually -// allocated by the internal heap mechanism -Token::~Token() { - coco_string_delete(val); -} - - -// ---------------------------------------------------------------------------- -// Buffer Implementation -// ---------------------------------------------------------------------------- - -Buffer::Buffer(Buffer* b) -: - buf(b->buf), - bufCapacity(b->bufCapacity), - bufLen(b->bufLen), - bufPos(b->bufPos), - bufStart(b->bufStart), - fileLen(b->fileLen), - cStream(b->cStream), - stdStream(b->stdStream), - isUserStream_(b->isUserStream_) -{ - // avoid accidental deletion on any of these members - b->buf = NULL; - b->cStream = NULL; - b->stdStream = NULL; -} - - -Buffer::Buffer(FILE* istr, bool isUserStream) -: - buf(NULL), - bufCapacity(0), - bufLen(0), - bufPos(0), - bufStart(0), - fileLen(0), - cStream(istr), - stdStream(NULL), - isUserStream_(isUserStream) -{ -// ensure binary read on windows -#if _MSC_VER >= 1300 - _setmode(_fileno(cStream), _O_BINARY); -#endif - - if (CanSeek()) { - fseek(cStream, 0, SEEK_END); - fileLen = ftell(cStream); - fseek(cStream, 0, SEEK_SET); - bufLen = (fileLen < MAX_BUFFER_LENGTH) ? fileLen : MAX_BUFFER_LENGTH; - bufStart = INT_MAX; // nothing in the buffer so far - } - - bufCapacity = (bufLen > 0) ? bufLen : MIN_BUFFER_LENGTH; - buf = new unsigned char[bufCapacity]; - if (fileLen > 0) SetPos(0); // setup buffer to position 0 (start) - else bufPos = 0; // index 0 is already after the file, thus Pos = 0 is invalid - if (bufLen == fileLen && CanSeek()) Close(); -} - - -Buffer::Buffer(std::istream* istr, bool isUserStream) -: - buf(NULL), - bufCapacity(0), - bufLen(0), - bufPos(0), - bufStart(0), - fileLen(0), - cStream(NULL), - stdStream(istr), - isUserStream_(isUserStream) -{ - // ensure binary read on windows -#if _MSC_VER >= 1300 - // TODO -#endif -} - - -Buffer::Buffer(std::string& str) -: - buf(NULL), - bufCapacity(0), - bufLen(0), - bufPos(0), - bufStart(0), - fileLen(0), - cStream(NULL), - stdStream(new std::istringstream(str)), - isUserStream_(false) -{} - - -Buffer::Buffer(const unsigned char* chars, int len) -: - buf(new unsigned char[len]), - bufCapacity(len), - bufLen(len), - bufPos(0), - bufStart(0), - fileLen(len), - cStream(NULL), - stdStream(NULL), - isUserStream_(false) -{ - memcpy(this->buf, chars, len*sizeof(char)); -} - - -Buffer::Buffer(const char* chars, int len) -: - buf(new unsigned char[len]), - bufCapacity(len), - bufLen(len), - bufPos(0), - bufStart(0), - fileLen(len), - cStream(NULL), - stdStream(NULL), - isUserStream_(false) -{ - memcpy(this->buf, chars, len*sizeof(char)); -} - - -Buffer::~Buffer() { - Close(); - if (buf) { - delete [] buf; - buf = NULL; - } -} - - -void Buffer::Close() { - if (!isUserStream_) { - if (cStream) { - fclose(cStream); - cStream = NULL; - } - else if (stdStream) { - delete stdStream; - stdStream = 0; - } - } -} - - -int Buffer::Read() { - if (stdStream) - { - int ch = stdStream->get(); - if (stdStream->eof()) - { - return EoF; - } - return ch; - } - - if (bufPos < bufLen) { - return buf[bufPos++]; - } else if (GetPos() < fileLen) { - SetPos(GetPos()); // shift buffer start to Pos - return buf[bufPos++]; - } else if (cStream && !CanSeek() && (ReadNextStreamChunk() > 0)) { - return buf[bufPos++]; - } else { - return EoF; - } -} - - -int UTF8Buffer::Read() { - int ch; - do { - ch = Buffer::Read(); - // until we find a utf8 start (0xxxxxxx or 11xxxxxx) - } while ((ch >= 128) && ((ch & 0xC0) != 0xC0) && (ch != EoF)); - if (ch < 128 || ch == EoF) { - // nothing to do, first 127 chars are the same in ascii and utf8 - // 0xxxxxxx or end of file character - } else if ((ch & 0xF0) == 0xF0) { - // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - int c1 = ch & 0x07; ch = Buffer::Read(); - int c2 = ch & 0x3F; ch = Buffer::Read(); - int c3 = ch & 0x3F; ch = Buffer::Read(); - int c4 = ch & 0x3F; - ch = (((((c1 << 6) | c2) << 6) | c3) << 6) | c4; - } else if ((ch & 0xE0) == 0xE0) { - // 1110xxxx 10xxxxxx 10xxxxxx - int c1 = ch & 0x0F; ch = Buffer::Read(); - int c2 = ch & 0x3F; ch = Buffer::Read(); - int c3 = ch & 0x3F; - ch = (((c1 << 6) | c2) << 6) | c3; - } else if ((ch & 0xC0) == 0xC0) { - // 110xxxxx 10xxxxxx - int c1 = ch & 0x1F; ch = Buffer::Read(); - int c2 = ch & 0x3F; - ch = (c1 << 6) | c2; - } - return ch; -} - - -int Buffer::Peek() { - int curPos = GetPos(); - int ch = Read(); - SetPos(curPos); - return ch; -} - - -int Buffer::GetPos() const { - if (stdStream) - { - return stdStream->tellg(); - } - - return bufPos + bufStart; -} - - -void Buffer::SetPos(int value) { - if (stdStream) - { - stdStream->seekg(value, std::ios::beg); - return; - } - - if ((value >= fileLen) && cStream && !CanSeek()) { - // Wanted position is after buffer and the stream - // is not seek-able e.g. network or console, - // thus we have to read the stream manually till - // the wanted position is in sight. - while ((value >= fileLen) && (ReadNextStreamChunk() > 0)) - {} - } - - if ((value < 0) || (value > fileLen)) { - wprintf(L"--- buffer out of bounds access, position: %d\n", value); - ::exit(1); - } - - if ((value >= bufStart) && (value < (bufStart + bufLen))) { // already in buffer - bufPos = value - bufStart; - } else if (cStream) { // must be swapped in - fseek(cStream, value, SEEK_SET); - bufLen = fread(buf, sizeof(char), bufCapacity, cStream); - bufStart = value; bufPos = 0; - } else { - bufPos = fileLen - bufStart; // make Pos return fileLen - } -} - - -// Read the next chunk of bytes from the stream, increases the buffer -// if needed and updates the fields fileLen and bufLen. -// Returns the number of bytes read. -int Buffer::ReadNextStreamChunk() { - int freeLen = bufCapacity - bufLen; - if (freeLen == 0) { - // in the case of a growing input stream - // we can neither seek in the stream, nor can we - // foresee the maximum length, thus we must adapt - // the buffer size on demand. - bufCapacity = bufLen * 2; - unsigned char *newBuf = new unsigned char[bufCapacity]; - memcpy(newBuf, buf, bufLen*sizeof(char)); - delete [] buf; - buf = newBuf; - freeLen = bufLen; - } - int read = fread(buf + bufLen, sizeof(char), freeLen, cStream); - if (read > 0) { - fileLen = bufLen = (bufLen + read); - return read; - } - // end of stream reached - return 0; -} - - -bool Buffer::CanSeek() const { - return cStream && (ftell(cStream) != -1); -} - - -// ---------------------------------------------------------------------------- -// Scanner Implementation -// ---------------------------------------------------------------------------- - -Scanner::Scanner(FILE* istr) -: - buffer(new Buffer(istr, true)) -{ - Init(); -} - - -Scanner::Scanner(std::istream& istr) -: - buffer(new Buffer(&istr, true)) -{ - Init(); -} - - -Scanner::Scanner(const wchar_t* fileName) { - char *chFileName = coco_string_create_char(fileName); - FILE* istr; - if ((istr = fopen(chFileName, "rb")) == NULL) { - wprintf(L"--- Cannot open file %ls\n", fileName); - ::exit(1); - } - coco_string_delete(chFileName); - buffer = new Buffer(istr, false); - Init(); -} - - -Scanner::Scanner(const unsigned char* buf, int len) -: - buffer(new Buffer(buf, len)) -{ - Init(); -} - - -Scanner::Scanner(const char* buf, int len) -: - buffer(new Buffer(buf, len)) -{ - Init(); -} - - -Scanner::~Scanner() { - char* cur = reinterpret_cast(firstHeap); - - while (cur) { - cur = *(reinterpret_cast(cur + HEAP_BLOCK_SIZE)); - free(firstHeap); - firstHeap = cur; - } - delete [] tval; - delete buffer; -} - - -void Scanner::Init() { - for (int i = 65; i <= 90; ++i) start.set(i, 1); - for (int i = 95; i <= 95; ++i) start.set(i, 1); - for (int i = 97; i <= 122; ++i) start.set(i, 1); - start.set(45, 21); - for (int i = 48; i <= 57; ++i) start.set(i, 9); - start.set(34, 2); - start.set(36, 5); - start.set(46, 7); - start.set(123, 14); - start.set(125, 15); - start.set(43, 22); - start.set(42, 16); - start.set(47, 17); - start.set(40, 18); - start.set(41, 19); - start.set(44, 20); - start.set(Buffer::EoF, -1); - - - - tvalLength = 128; - tval = new wchar_t[tvalLength]; // text of current token - tlen = 0; - tval[tlen] = 0; - - // HEAP_BLOCK_SIZE byte heap + pointer to next heap block - heap = malloc(HEAP_BLOCK_SIZE + sizeof(void*)); - firstHeap = heap; - heapEnd = - reinterpret_cast - (reinterpret_cast(heap) + HEAP_BLOCK_SIZE); - *heapEnd = 0; - heapTop = heap; - if (sizeof(Token) > HEAP_BLOCK_SIZE) { - wprintf(L"--- Too small HEAP_BLOCK_SIZE\n"); - ::exit(1); - } - - pos = -1; line = 1; col = 0; - oldEols = 0; - NextCh(); - if (ch == 0xEF) { // check optional byte order mark for UTF-8 - NextCh(); int ch1 = ch; - NextCh(); int ch2 = ch; - if (ch1 != 0xBB || ch2 != 0xBF) { - wprintf(L"Illegal byte order mark at start of file"); - ::exit(1); - } - Buffer *oldBuf = buffer; - buffer = new UTF8Buffer(buffer); col = 0; - delete oldBuf; oldBuf = NULL; - NextCh(); - } - - - pt = tokens = CreateToken(); // first token is a dummy -} - - -void Scanner::NextCh() { - if (oldEols > 0) { - ch = EOL; - oldEols--; - } - else { - pos = buffer->GetPos(); - ch = buffer->Read(); col++; - // replace isolated '\r' by '\n' in order to make - // eol handling uniform across Windows, Unix and Mac - if (ch == L'\r' && buffer->Peek() != L'\n') ch = EOL; - if (ch == EOL) { line++; col = 0; } - } - -} - - -void Scanner::AddCh() { - if (tlen >= tvalLength) { - tvalLength *= 2; - wchar_t *newBuf = new wchar_t[tvalLength]; - memcpy(newBuf, tval, tlen*sizeof(wchar_t)); - delete [] tval; - tval = newBuf; - } - if (ch != Buffer::EoF) { - tval[tlen++] = ch; - NextCh(); - } -} - - - -bool Scanner::Comment0() { - int level = 1, pos0 = pos, line0 = line, col0 = col; - NextCh(); - if (ch == L'/') { - NextCh(); - for(;;) { - if (ch == 10) { - level--; - if (level == 0) { oldEols = line - line0; NextCh(); return true; } - NextCh(); - } else if (ch == buffer->EoF) return false; - else NextCh(); - } - } else { - buffer->SetPos(pos0); NextCh(); line = line0; col = col0; - } - return false; -} - -bool Scanner::Comment1() { - int level = 1, pos0 = pos, line0 = line, col0 = col; - NextCh(); - if (ch == L'*') { - NextCh(); - for(;;) { - if (ch == L'*') { - NextCh(); - if (ch == L'/') { - level--; - if (level == 0) { oldEols = line - line0; NextCh(); return true; } - NextCh(); - } - } else if (ch == L'/') { - NextCh(); - if (ch == L'*') { - level++; NextCh(); - } - } else if (ch == buffer->EoF) return false; - else NextCh(); - } - } else { - buffer->SetPos(pos0); NextCh(); line = line0; col = col0; - } - return false; -} - - -void Scanner::CreateHeapBlock() { - char* cur = reinterpret_cast(firstHeap); - - // release unused blocks - while - ( - (reinterpret_cast(tokens) < cur) - || (reinterpret_cast(tokens) > (cur + HEAP_BLOCK_SIZE)) - ) { - cur = *(reinterpret_cast(cur + HEAP_BLOCK_SIZE)); - free(firstHeap); - firstHeap = cur; - } - - // HEAP_BLOCK_SIZE byte heap + pointer to next heap block - void* newHeap = malloc(HEAP_BLOCK_SIZE + sizeof(void*)); - *heapEnd = newHeap; - heapEnd = - reinterpret_cast - (reinterpret_cast(newHeap) + HEAP_BLOCK_SIZE); - *heapEnd = 0; - heap = newHeap; - heapTop = heap; -} - - -Token* Scanner::CreateToken() { - const int reqMem = sizeof(Token); - if - ( - (reinterpret_cast(heapTop) + reqMem) - >= reinterpret_cast(heapEnd) - ) { - CreateHeapBlock(); - } - // token 'occupies' heap starting at heapTop - Token* tok = reinterpret_cast(heapTop); - // increment past this part of the heap, which is now used - heapTop = - reinterpret_cast - (reinterpret_cast(heapTop) + reqMem); - tok->val = NULL; - tok->next = NULL; - return tok; -} - - -void Scanner::AppendVal(Token* tok) { - const int reqMem = (tlen + 1) * sizeof(wchar_t); - if - ( - (reinterpret_cast(heapTop) + reqMem) - >= reinterpret_cast(heapEnd) - ) { - if (reqMem > HEAP_BLOCK_SIZE) { - wprintf(L"--- Too long token value\n"); - ::exit(1); - } - CreateHeapBlock(); - } - - // add text value from heap - tok->val = reinterpret_cast(heapTop); - - // increment past this part of the heap, which is now used - heapTop = - reinterpret_cast - (reinterpret_cast(heapTop) + reqMem); - - // copy the currently parsed tval into the token - wcsncpy(tok->val, tval, tlen); - tok->val[tlen] = L'\0'; -} - - -Token* Scanner::NextToken() { - while (ch == ' ' || - (ch >= 9 && ch <= 10) || ch == 13 - ) NextCh(); - if ((ch == L'/' && Comment0()) || (ch == L'/' && Comment1())) return NextToken(); - t = CreateToken(); - t->pos = pos; t->col = col; t->line = line; - int state = start.state(ch); - tlen = 0; AddCh(); - - switch (state) { - case -1: { t->kind = eofSym; break; } // NextCh already done - case 0: { t->kind = noSym; break; } // NextCh already done - case 1: - case_1: - if ((ch >= L'0' && ch <= L'9') || (ch >= L'A' && ch <= L'Z') || ch == L'_' || (ch >= L'a' && ch <= L'z')) {AddCh(); goto case_1;} - else {t->kind = 1; break;} - case 2: - case_2: - if (ch <= 9 || (ch >= 11 && ch <= 12) || (ch >= 14 && ch <= L'!') || (ch >= L'#' && ch <= L'[') || (ch >= L']' && ch <= 65535)) {AddCh(); goto case_2;} - else if (ch == L'"') {AddCh(); goto case_4;} - else if (ch == 92) {AddCh(); goto case_3;} - else {t->kind = noSym; break;} - case 3: - case_3: - if ((ch >= L' ' && ch <= L'~')) {AddCh(); goto case_2;} - else {t->kind = noSym; break;} - case 4: - case_4: - {t->kind = 2; break;} - case 5: - if ((ch >= L'A' && ch <= L'Z') || ch == L'_' || (ch >= L'a' && ch <= L'z')) {AddCh(); goto case_6;} - else {t->kind = noSym; break;} - case 6: - case_6: - if ((ch >= L'0' && ch <= L'9') || (ch >= L'A' && ch <= L'Z') || ch == L'_' || (ch >= L'a' && ch <= L'z')) {AddCh(); goto case_6;} - else {t->kind = 3; break;} - case 7: - case_7: - if ((ch >= L'0' && ch <= L'9')) {AddCh(); goto case_8;} - else {t->kind = noSym; break;} - case 8: - case_8: - if ((ch >= L'0' && ch <= L'9')) {AddCh(); goto case_8;} - else {t->kind = 4; break;} - case 9: - case_9: - if ((ch >= L'0' && ch <= L'9')) {AddCh(); goto case_9;} - else if (ch == L'E' || ch == L'e') {AddCh(); goto case_10;} - else if (ch == L'.') {AddCh(); goto case_13;} - else {t->kind = 4; break;} - case 10: - case_10: - if ((ch >= L'0' && ch <= L'9')) {AddCh(); goto case_12;} - else if (ch == L'+' || ch == L'-') {AddCh(); goto case_11;} - else {t->kind = noSym; break;} - case 11: - case_11: - if ((ch >= L'0' && ch <= L'9')) {AddCh(); goto case_12;} - else {t->kind = noSym; break;} - case 12: - case_12: - if ((ch >= L'0' && ch <= L'9')) {AddCh(); goto case_12;} - else {t->kind = 4; break;} - case 13: - case_13: - if ((ch >= L'0' && ch <= L'9')) {AddCh(); goto case_13;} - else if (ch == L'E' || ch == L'e') {AddCh(); goto case_10;} - else {t->kind = 4; break;} - case 14: - {t->kind = 5; break;} - case 15: - {t->kind = 6; break;} - case 16: - {t->kind = 9; break;} - case 17: - {t->kind = 10; break;} - case 18: - {t->kind = 11; break;} - case 19: - {t->kind = 12; break;} - case 20: - {t->kind = 13; break;} - case 21: - if (ch == L'.') {AddCh(); goto case_7;} - else {t->kind = 8; break;} - case 22: - if (ch == L'.') {AddCh(); goto case_7;} - else {t->kind = 7; break;} - - } - AppendVal(t); - return t; -} - - -// get the next token (possibly a token already seen during peeking) -Token* Scanner::Scan() { - if (tokens->next == NULL) { - return pt = tokens = NextToken(); - } else { - pt = tokens = tokens->next; - return tokens; - } -} - - -// peek for the next token, ignore pragmas -Token* Scanner::Peek() { - do { - if (pt->next == NULL) { - pt->next = NextToken(); - } - pt = pt->next; - } while (pt->kind > maxT); // skip pragmas - - return pt; -} - - -// make sure that peeking starts at the current scan position -void Scanner::ResetPeek() { - pt = tokens; -} - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -} // namespace -} // namespace -} // namespace - - -// ************************************************************************* // diff --git a/applications/test/dictionary/calcEntry/calcEntryScanner.h b/applications/test/dictionary/calcEntry/calcEntryScanner.h deleted file mode 100644 index 9ea17302c6..0000000000 --- a/applications/test/dictionary/calcEntry/calcEntryScanner.h +++ /dev/null @@ -1,396 +0,0 @@ - - -#ifndef COCO_calcEntrySCANNER_H__ -#define COCO_calcEntrySCANNER_H__ - -#include -#include -#include -#include -#include -#include -#include -#include - -// io.h and fcntl are used to ensure binary read from streams on windows -#if _MSC_VER >= 1300 -#include -#include -#endif - -#if _MSC_VER >= 1400 -#define coco_swprintf swprintf_s -#elif _MSC_VER >= 1300 -#define coco_swprintf _snwprintf -#else -// assume every other compiler knows swprintf -#define coco_swprintf swprintf -#endif - - -#define COCO_WCHAR_MAX 65535 - - -namespace Foam { -namespace functionEntries { -namespace calcEntryInternal { - - - -// * * * * * * * * * * Wide Character String Routines * * * * * * * * * * * // - -// -// string handling, wide character -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -//! Create by copying str -wchar_t* coco_string_create(const wchar_t* str); - -//! Create a substring of str starting at index and length characters long -wchar_t* coco_string_create(const wchar_t* str, int index, int length); - -//! Create a lowercase string from str -wchar_t* coco_string_create_lower(const wchar_t* str); - -//! Create a lowercase substring from str starting at index and length characters long -wchar_t* coco_string_create_lower(const wchar_t* str, int index, int length); - -//! Create a string by concatenating str1 and str2 -wchar_t* coco_string_create_append(const wchar_t* str1, const wchar_t* str2); - -//! Create a string by concatenating a character to the end of str -wchar_t* coco_string_create_append(const wchar_t* str, const wchar_t ch); - -//! Free storage and nullify the argument -void coco_string_delete(wchar_t* &str); - -//! The length of the str, or 0 if the str is NULL -int coco_string_length(const wchar_t* str); - -//! Return true if the str ends with the endstr -bool coco_string_endswith(const wchar_t* str, const wchar_t* endstr); - -//! Return the index of the first occurrence of ch. -// Return -1 if nothing is found. -int coco_string_indexof(const wchar_t* str, const wchar_t ch); - -//! Return the index of the last occurrence of ch. -// Return -1 if nothing is found. -int coco_string_lastindexof(const wchar_t* str, const wchar_t ch); - -//! Append str to dest -void coco_string_merge(wchar_t* &dest, const wchar_t* str); - -//! Compare strings, return true if they are equal -bool coco_string_equal(const wchar_t* str1, const wchar_t* str2); - -//! Compare strings, return 0 if they are equal -int coco_string_compareto(const wchar_t* str1, const wchar_t* str2); - -//! Simple string hashing function -int coco_string_hash(const wchar_t* str); - -// -// String conversions -// ~~~~~~~~~~~~~~~~~~ - -//! Convert wide string to double -double coco_string_toDouble(const wchar_t* str); - -//! Convert wide string to float -float coco_string_toFloat(const wchar_t* str); - -// -// String handling, byte character -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -//! Create by copying byte str -wchar_t* coco_string_create(const char* str); - -//! Create a substring of byte str starting at index and length characters long -wchar_t* coco_string_create(const char* str, int index, int length); - -//! Create a byte string by copying str -char* coco_string_create_char(const wchar_t* str); - -//! Create a byte substring of str starting at index and length characters long -char* coco_string_create_char(const wchar_t* str, int index, int length); - -//! Free storage and nullify the argument -void coco_string_delete(char* &str); - - -// -// String conversions, byte character -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -//! Convert byte string to double -double coco_string_toDouble(const char* str); - -//! Convert byte string to float -float coco_string_toFloat(const char* str); - -// * * * * * * * * * End of Wide Character String Routines * * * * * * * * * // - - -//! Scanner Token -class Token -{ -public: - int kind; //!< token kind - int pos; //!< token position in the source text (starting at 0) - int col; //!< token column (starting at 1) - int line; //!< token line (starting at 1) - wchar_t* val; //!< token value - Token *next; //!< Peek tokens are kept in linked list - - Token(); //!< Construct null - ~Token(); //!< Destructor - cleanup allocated val?? -}; - - -//! Scanner Buffer -// -//! This Buffer supports the following cases: -//! -# seekable stream (file) -//! -# whole stream in buffer -//! -# part of stream in buffer -//! -# non seekable stream (network, console) -class Buffer { -private: - unsigned char *buf; //!< input buffer - int bufCapacity; //!< capacity of buf - int bufLen; //!< length of buffer - int bufPos; //!< current position in buffer - int bufStart; //!< position of first byte in buffer relative to input stream - int fileLen; //!< length of input stream (may change if the stream is no file) - FILE* cStream; //!< input stdio stream (normally seekable) - std::istream* stdStream; //!< STL std stream (seekable) - bool isUserStream_; //!< was the stream opened by the user? - - int ReadNextStreamChunk(); - bool CanSeek() const; //!< true if stream can be seeked otherwise false - -protected: - Buffer(Buffer*); //!< for the UTF8Buffer - -public: - static const int EoF = COCO_WCHAR_MAX + 1; - - //! Attach buffer to a stdio stream. - //! User streams are not closed in the destructor - Buffer(FILE*, bool isUserStream = true); - - //! Attach buffer to an STL std stream - //! User streams are not closed in the destructor - explicit Buffer(std::istream*, bool isUserStream = true); - - //! Copy buffer contents from constant string - //! Handled internally as an istringstream - explicit Buffer(std::string&); - - //! Copy buffer contents from constant character string - Buffer(const unsigned char* chars, int len); - //! Copy buffer contents from constant character string - Buffer(const char* chars, int len); - - //! Close stream (but not user streams) and free buf (if any) - virtual ~Buffer(); - - virtual void Close(); //!< Close stream (but not user streams) - virtual int Read(); //!< Get character from stream or buffer - virtual int Peek(); //!< Peek character from stream or buffer - - virtual int GetPos() const; - virtual void SetPos(int value); -}; - - -//! A Scanner buffer that handles UTF-8 characters -class UTF8Buffer : public Buffer { -public: - UTF8Buffer(Buffer* b) : Buffer(b) {} - virtual int Read(); -}; - - -//------------------------------------------------------------------------------ -// StartStates -//------------------------------------------------------------------------------ -//! maps characters (integers) to start states of tokens -class StartStates { - class Elem { - public: - int key, val; - Elem *next; - Elem(int k, int v) : - key(k), val(v), next(0) - {} - }; - - Elem **tab; - -public: - StartStates() : - tab(new Elem*[128]) - { - memset(tab, 0, 128*sizeof(Elem*)); - } - - virtual ~StartStates() { - for (int i = 0; i < 128; ++i) { - Elem *e = tab[i]; - while (e) { - Elem *next = e->next; - delete e; - e = next; - } - } - delete [] tab; - } - - void set(int key, int val) { - Elem *e = new Elem(key, val); - const int k = unsigned(key) % 128; - e->next = tab[k]; - tab[k] = e; - } - - int state(int key) { - Elem *e = tab[unsigned(key) % 128]; - while (e && e->key != key) e = e->next; - return e ? e->val : 0; - } -}; - - -//------------------------------------------------------------------------------ -// KeywordMap -//------------------------------------------------------------------------------ -//! maps strings to integers (identifiers to keyword kinds) -class KeywordMap { - class Elem { - public: - wchar_t *key; - int val; - Elem *next; - Elem(const wchar_t *k, int v) : - key(coco_string_create(k)), val(v), next(0) - {} - virtual ~Elem() { - coco_string_delete(key); - } - }; - - Elem **tab; - -public: - KeywordMap() : - tab(new Elem*[128]) - { - memset(tab, 0, 128*sizeof(Elem*)); - } - - virtual ~KeywordMap() { - for (int i = 0; i < 128; ++i) { - Elem *e = tab[i]; - while (e) { - Elem *next = e->next; - delete e; - e = next; - } - } - delete [] tab; - } - - void set(const wchar_t *key, int val) { - Elem *e = new Elem(key, val); - const int k = coco_string_hash(key) % 128; - e->next = tab[k]; - tab[k] = e; - } - - int get(const wchar_t *key, int defaultVal) { - Elem *e = tab[coco_string_hash(key) % 128]; - while (e && !coco_string_equal(e->key, key)) e = e->next; - return e ? e->val : defaultVal; - } -}; - - -//! A Coco/R Scanner -class Scanner { -private: - static const int maxT = 14; - static const int noSym = 14; - - static const int eofSym = 0; //!< end-of-file token id - static const char EOL = '\n'; //!< end-of-line character - - void *firstHeap; //!< the start of the heap management - void *heap; //!< the currently active block - void *heapTop; //!< the top of the heap - void **heapEnd; //!< the end of the last heap block - - StartStates start; //!< A map of start states for particular characters - KeywordMap keywords; //!< A hash of keyword literals to token kind - - Token *t; //!< current token - wchar_t *tval; //!< text of current token - int tvalLength; //!< maximum capacity (length) for tval - int tlen; //!< length of tval - - Token *tokens; //!< list of tokens already peeked (first token is a dummy) - Token *pt; //!< current peek token - - int ch; //!< current input character - - int pos; //!< byte position of current character - int line; //!< line number of current character - int col; //!< column number of current character - int oldEols; //!< the number of EOLs that appeared in a comment - - void CreateHeapBlock(); //!< add a heap block, freeing unused ones - Token* CreateToken(); //!< fit token on the heap - void AppendVal(Token* tok); //!< adjust tok->val to point to the heap and copy tval into it - - void Init(); //!< complete the initialization for the constructors - void NextCh(); //!< get the next input character into ch - void AddCh(); //!< append the character ch to tval - bool Comment0(); - bool Comment1(); - - Token* NextToken(); //!< get the next token - -public: - //! The scanner buffer - Buffer *buffer; - - //! Using an existing open file handle for the scanner - Scanner(FILE*); - - //! Using an existing open STL std stream - explicit Scanner(std::istream&); - - //! Open a file for reading and attach scanner - explicit Scanner(const wchar_t* fileName); - - //! Attach scanner to an existing character buffer - Scanner(const unsigned char* chars, int len); - //! Attach scanner to an existing character buffer - Scanner(const char* chars, int len); - - ~Scanner(); //!< free heap and allocated memory - Token* Scan(); //!< get the next token (possibly a token already seen during peeking) - Token* Peek(); //!< peek for the next token, ignore pragmas - void ResetPeek(); //!< ensure that peeking starts at the current scan position - -}; // end Scanner - -} // namespace -} // namespace -} // namespace - - -#endif // COCO_calcEntrySCANNER_H__ - diff --git a/wmake/rules/General/coco b/wmake/rules/General/coco new file mode 100644 index 0000000000..12c11df4cf --- /dev/null +++ b/wmake/rules/General/coco @@ -0,0 +1,6 @@ +.SUFFIXES: .ATG + +ATGtoo = Coco -single -frames $(WM_THIRD_PARTY_DIR)/coco-r/src $$SOURCE -o $(OBJECTS_DIR) ; $(CC) $(c++FLAGS) -c $*.cpp -o $@ + +.ATG.dep: + $(MAKE_DEP) diff --git a/wmake/rules/General/standard b/wmake/rules/General/standard index 809f9353a2..3188ac4413 100644 --- a/wmake/rules/General/standard +++ b/wmake/rules/General/standard @@ -4,6 +4,7 @@ include $(GENERAL_RULES)/sourceToDep include $(GENERAL_RULES)/flex include $(GENERAL_RULES)/flex++ +include $(GENERAL_RULES)/coco ## include $(GENERAL_RULES)/byacc ## include $(GENERAL_RULES)/btyacc++ include $(GENERAL_RULES)/bison From e0ba4cbb02dd8e5c8f271a41ac1bcd5de5e986c5 Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Sun, 3 Jan 2010 21:45:32 +0100 Subject: [PATCH 006/250] Adjust line number before/after #calc{} scanner for improved error messages. --- applications/test/dictionary/Make/files | 2 +- applications/test/dictionary/calcEntry/calcEntry.C | 14 ++++++++++---- .../{calcEntryParser.ATG => calcEntryParser.atg} | 0 wmake/rules/General/coco | 8 +++++--- 4 files changed, 16 insertions(+), 8 deletions(-) rename applications/test/dictionary/calcEntry/{calcEntryParser.ATG => calcEntryParser.atg} (100%) diff --git a/applications/test/dictionary/Make/files b/applications/test/dictionary/Make/files index 89d95d0298..6f1da0059a 100644 --- a/applications/test/dictionary/Make/files +++ b/applications/test/dictionary/Make/files @@ -1,6 +1,6 @@ dictionaryTest.C -calcEntry/calcEntryParser.ATG +calcEntry/calcEntryParser.atg calcEntry/calcEntryInternal.C calcEntry/calcEntry.C diff --git a/applications/test/dictionary/calcEntry/calcEntry.C b/applications/test/dictionary/calcEntry/calcEntry.C index 7e634bc8b4..0f0bfbbdc8 100644 --- a/applications/test/dictionary/calcEntry/calcEntry.C +++ b/applications/test/dictionary/calcEntry/calcEntry.C @@ -68,17 +68,23 @@ bool Foam::functionEntries::calcEntry::execute myErrorHandler("calcEntryInternal::Parser"); calcEntryInternal::Scanner scanner(iss); + + // set the starting line + scanner.Line(is.lineNumber()); + calcEntryInternal::Parser parser(&scanner, &myErrorHandler); // Attach dictionary context parser.dict(parentDict); - // Attach scalar functions - // parser.functions(parentDict); - parser.Parse(); - // make a small input list to contain the answer + // mostly have an extra newline in the lookahead token + // so subtract 1 to keep things vaguely in sync + // (this is still far from perfect) + is.lineNumber() = scanner.Line() - 1; + + // a small input list to contain the answer tokenList tokens(2); tokens[0] = parser.Result(); tokens[1] = token::END_STATEMENT; diff --git a/applications/test/dictionary/calcEntry/calcEntryParser.ATG b/applications/test/dictionary/calcEntry/calcEntryParser.atg similarity index 100% rename from applications/test/dictionary/calcEntry/calcEntryParser.ATG rename to applications/test/dictionary/calcEntry/calcEntryParser.atg diff --git a/wmake/rules/General/coco b/wmake/rules/General/coco index 12c11df4cf..97b345c512 100644 --- a/wmake/rules/General/coco +++ b/wmake/rules/General/coco @@ -1,6 +1,8 @@ -.SUFFIXES: .ATG +# handie Coco/R attributed grammars -ATGtoo = Coco -single -frames $(WM_THIRD_PARTY_DIR)/coco-r/src $$SOURCE -o $(OBJECTS_DIR) ; $(CC) $(c++FLAGS) -c $*.cpp -o $@ +.SUFFIXES: .atg -.ATG.dep: +atgtoo = Coco -single -frames $(WM_THIRD_PARTY_DIR)/coco-cpp/src $$SOURCE -o $(OBJECTS_DIR) ; $(CC) $(c++FLAGS) -c $*.cpp -o $@ + +.atg.dep: $(MAKE_DEP) From aa217c28678d84cedad3544054f42bc9c257b4e5 Mon Sep 17 00:00:00 2001 From: mattijs Date: Tue, 5 Jan 2010 22:13:45 +0000 Subject: [PATCH 007/250] Added combine function to combine two pointConstraints --- .../pointConstraint/pointConstraint.H | 3 ++ .../pointConstraint/pointConstraintI.H | 41 +++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/src/OpenFOAM/fields/pointPatchFields/pointPatchField/pointConstraint/pointConstraint.H b/src/OpenFOAM/fields/pointPatchFields/pointPatchField/pointConstraint/pointConstraint.H index 5e28ac1e14..10aa63f2c9 100644 --- a/src/OpenFOAM/fields/pointPatchFields/pointPatchField/pointConstraint/pointConstraint.H +++ b/src/OpenFOAM/fields/pointPatchFields/pointPatchField/pointConstraint/pointConstraint.H @@ -77,6 +77,9 @@ public: //- Apply and accumulate the effect of the given constraint direction inline void applyConstraint(const vector& cd); + //- Combine constraints + inline void combine(const pointConstraint&); + //- Return the accumulated constraint transformation tensor inline tensor constraintTransformation() const; }; diff --git a/src/OpenFOAM/fields/pointPatchFields/pointPatchField/pointConstraint/pointConstraintI.H b/src/OpenFOAM/fields/pointPatchFields/pointPatchField/pointConstraint/pointConstraintI.H index a0af05b5af..c488bf603e 100644 --- a/src/OpenFOAM/fields/pointPatchFields/pointPatchField/pointConstraint/pointConstraintI.H +++ b/src/OpenFOAM/fields/pointPatchFields/pointPatchField/pointConstraint/pointConstraintI.H @@ -69,6 +69,47 @@ void Foam::pointConstraint::applyConstraint(const vector& cd) } +void Foam::pointConstraint::combine(const pointConstraint& pc) +{ + if (first() == 0) + { + operator=(pc); + } + else if (first() == 1) + { + // Save single normal + vector n = second(); + // Apply to supplied point constaint + operator=(pc); + applyConstraint(n); + } + else if (first() == 2) + { + if (pc.first() == 0) + {} + else if (pc.first() == 1) + { + applyConstraint(pc.second()); + } + else if (pc.first() == 2) + { + // Both constrained to line. Same (+-)direction? + if (mag(second() & pc.second()) <= (1.0-1e-3)) + { + // Different directions + first() = 3; + second() = vector::zero; + } + } + else + { + first() = 3; + second() = vector::zero; + } + } +} + + Foam::tensor Foam::pointConstraint::constraintTransformation() const { if (first() == 0) From cf3e2a8abff5769a1a48ca5f392808eaedb4e31b Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Wed, 6 Jan 2010 12:27:14 +0100 Subject: [PATCH 008/250] Update calcEntry grammar to include copyright. Include character class (wchar_t or char) as a template parameter in CocoParserErrors. --- .../test/dictionary/calcEntry/calcEntryParser.atg | 14 +++++++++----- src/OpenFOAM/db/error/CocoParserErrors.H | 14 +++++++------- wmake/rules/General/coco | 7 ++++++- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/applications/test/dictionary/calcEntry/calcEntryParser.atg b/applications/test/dictionary/calcEntry/calcEntryParser.atg index e1a1567700..7dfb17c107 100644 --- a/applications/test/dictionary/calcEntry/calcEntryParser.atg +++ b/applications/test/dictionary/calcEntry/calcEntryParser.atg @@ -1,8 +1,9 @@ +[copy] /*---------------------------------*- C++ -*---------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2009-2010 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -27,15 +28,19 @@ License Description An attributed Coco/R grammar to parse simple arithmetic expressions + Includes support for dictionary $variables and some scalar functions + (eg, sin, pow, ...) + SourceFiles generated \*---------------------------------------------------------------------------*/ +[/copy] /*---------------------------------------------------------------------------*\ compile with: Coco \ [-single] -frames $WM_THIRD_PARTY_DIR/coco-r \ - calcEntryParser.ATG + calcEntryParser.atg \*---------------------------------------------------------------------------*/ #include "dictionary.H" @@ -49,8 +54,6 @@ COMPILER calcEntry $namespace=Foam::functionEntries::calcEntryInternal $eof=true // grammar handles eof itself - // Simple four function calculator for OpenFOAM dictionaries - private: //- The parent dictionary dictionary* dict_; @@ -125,9 +128,10 @@ public: } -INITIALIZE +[initialize] dict_ = 0; val = 0; +[/initialize] /*---------------------------------------------------------------------------*/ diff --git a/src/OpenFOAM/db/error/CocoParserErrors.H b/src/OpenFOAM/db/error/CocoParserErrors.H index 21f574592d..d9d2155db2 100644 --- a/src/OpenFOAM/db/error/CocoParserErrors.H +++ b/src/OpenFOAM/db/error/CocoParserErrors.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2009-2009 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2009-2010 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -45,7 +45,7 @@ namespace Foam Class CocoParserErrors Declaration \*---------------------------------------------------------------------------*/ -template +template class CocoParserErrors : public BaseClass @@ -90,14 +90,14 @@ public: // Error Handling //- Handle a general warning 'msg' - virtual void Warning(const wchar_t* msg) + virtual void Warning(const CharClass* msg) { WarningIn(name_) << msg << endl; } //- Handle a general warning 'msg' - virtual void Warning(int line, int col, const wchar_t* msg) + virtual void Warning(int line, int col, const CharClass* msg) { WarningIn(name_) <<"line " << line << " col " << col << ": " @@ -105,7 +105,7 @@ public: } //- Handle general error 'msg' (eg, a semantic error) - virtual void Error(int line, int col, const wchar_t* msg) + virtual void Error(int line, int col, const CharClass* msg) { FatalErrorIn(name_) << "line " << line << " col " << col <<": " << msg << endl @@ -113,7 +113,7 @@ public: } //- Handle general error 'msg' (eg, a semantic error) - virtual void Error(const wchar_t* msg) + virtual void Error(const CharClass* msg) { FatalErrorIn(name_) << msg << endl @@ -121,7 +121,7 @@ public: } //- Handle a general exception 'msg' - virtual void Exception(const wchar_t* msg) + virtual void Exception(const CharClass* msg) { this->Error(msg); } diff --git a/wmake/rules/General/coco b/wmake/rules/General/coco index 97b345c512..46fae00453 100644 --- a/wmake/rules/General/coco +++ b/wmake/rules/General/coco @@ -2,7 +2,12 @@ .SUFFIXES: .atg -atgtoo = Coco -single -frames $(WM_THIRD_PARTY_DIR)/coco-cpp/src $$SOURCE -o $(OBJECTS_DIR) ; $(CC) $(c++FLAGS) -c $*.cpp -o $@ +atgtoo = \ + $(WM_THIRD_PARTY_DIR)/coco-cpp/platforms/$(WM_ARCH)/bin/coco-cpp \ + -single \ + -frames $(WM_THIRD_PARTY_DIR)/coco-cpp/platforms/share/coco-cpp \ + $$SOURCE -o $(OBJECTS_DIR) ; \ + $(CC) $(c++FLAGS) -c $*.cpp -o $@ .atg.dep: $(MAKE_DEP) From a132aadeb80bec0c67df902882f3f65bbe0b546f Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Mon, 11 Jan 2010 15:00:55 +0100 Subject: [PATCH 009/250] Output wchar_t as UTF-8 instead of simply truncating to char. --- src/OpenFOAM/primitives/chars/wchar/wchar.H | 10 ++- src/OpenFOAM/primitives/chars/wchar/wcharIO.C | 74 ++++++++++++++++--- 2 files changed, 72 insertions(+), 12 deletions(-) diff --git a/src/OpenFOAM/primitives/chars/wchar/wchar.H b/src/OpenFOAM/primitives/chars/wchar/wchar.H index c731a3dc81..61519a51d3 100644 --- a/src/OpenFOAM/primitives/chars/wchar/wchar.H +++ b/src/OpenFOAM/primitives/chars/wchar/wchar.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2009-2009 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2009-2010 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -31,6 +31,10 @@ Description SourceFiles wcharIO.C +SeeAlso + http://en.wikipedia.org/wiki/UTF-8 + http://en.wikibooks.org/wiki/Unicode/Character_reference + \*---------------------------------------------------------------------------*/ #ifndef wchar_H @@ -48,10 +52,10 @@ class Ostream; // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * // -//- Output via a normal char +//- Output wide character (Unicode) as UTF-8 Ostream& operator<<(Ostream&, const wchar_t); -//- Output string via normal char +//- Output wide character (Unicode) string as UTF-8 Ostream& operator<<(Ostream&, const wchar_t*); diff --git a/src/OpenFOAM/primitives/chars/wchar/wcharIO.C b/src/OpenFOAM/primitives/chars/wchar/wcharIO.C index 47a5ed0560..9796d4b6eb 100644 --- a/src/OpenFOAM/primitives/chars/wchar/wcharIO.C +++ b/src/OpenFOAM/primitives/chars/wchar/wcharIO.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2009-2009 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2009-2010 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -22,11 +22,6 @@ License along with OpenFOAM; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -Description - Reads a char from an input stream, for a given version - number and File format. If an ascii File is being read, then the line - numbers are counted and an erroneous read is reported. - \*---------------------------------------------------------------------------*/ #include "error.H" @@ -38,7 +33,68 @@ Description Foam::Ostream& Foam::operator<<(Ostream& os, const wchar_t wc) { - os.write(char(wc)); + if (!(wc & ~0x0000007F)) + { + // 0x00000000 - 0x0000007F: (1-byte output) + // 0xxxxxxx + os.write(char(wc)); + } + else if (!(wc & ~0x000007FF)) + { + // 0x00000080 - 0x000007FF: (2-byte output) + // 110bbbaa 10aaaaaa + os.write(char(0xC0 | ((wc >> 6) & 0x1F))); + os.write(char(0x80 | ((wc) & 0x3F))); + } + else if (!(wc & ~0x0000FFFF)) + { + // 0x00000800 - 0x0000FFFF: (3-byte output) + // 1110bbbb 10bbbbaa 10aaaaaa + os.write(char(0xE0 | ((wc >> 12) & 0x0F))); + os.write(char(0x80 | ((wc >> 6) & 0x3F))); + os.write(char(0x80 | ((wc) & 0x3F))); + } + else if (!(wc & ~0x001FFFFF)) + { + // 0x00010000 - 0x001FFFFF: (4-byte output) + // 11110ccc 10ccbbbb 10bbbbaa 10aaaaaa + os.write(char(0xF0 | ((wc >> 18) & 0x07))); + os.write(char(0x80 | ((wc >> 12) & 0x3F))); + os.write(char(0x80 | ((wc >> 6) & 0x3F))); + os.write(char(0x80 | ((wc) & 0x3F))); + } + else if (!(wc & ~0x03FFFFFF)) + { + // 0x00200000 - 0x03FFFFFF: (5-byte output) + // 111110dd 10cccccc 10ccbbbb 10bbbbaa 10aaaaaa + os.write(char(0xF8 | ((wc >> 24) & 0x03))); + os.write(char(0x80 | ((wc >> 18) & 0x3F))); + os.write(char(0x80 | ((wc >> 12) & 0x3F))); + os.write(char(0x80 | ((wc >> 6) & 0x3F))); + os.write(char(0x80 | ((wc) & 0x3F))); + } + else if (!(wc & ~0x7FFFFFFF)) + { + // 0x04000000 - 0x7FFFFFFF: (6-byte output) + // 1111110d 10dddddd 10cccccc 10ccbbbb 10bbbbaa 10aaaaaa + os.write(char(0xFC | ((wc >> 30) & 0x01))); + os.write(char(0x80 | ((wc >> 24) & 0x3F))); + os.write(char(0x80 | ((wc >> 18) & 0x3F))); + os.write(char(0x80 | ((wc >> 12) & 0x3F))); + os.write(char(0x80 | ((wc >> 6) & 0x3F))); + os.write(char(0x80 | ((wc) & 0x3F))); + } + else + { + // according to man page utf8(7) + // the Unicode standard specifies no characters above 0x0010FFFF, + // so Unicode characters can only be up to four bytes long in UTF-8. + + // report anything unknown/invalid as replacement character U+FFFD + os.write(char(0xEF)); + os.write(char(0xBF)); + os.write(char(0xBD)); + } os.check("Ostream& operator<<(Ostream&, const wchar_t)"); return os; @@ -51,10 +107,10 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const wchar_t* ws) { for (const wchar_t* p = ws; *p; ++p) { - os.write(char(*p)); + os << *p; } } - os.check("Ostream& operator<<(Ostream&, const wchar_t*)"); + return os; } From 210f2305b6085906d6a4ce80b152ac2412bee92c Mon Sep 17 00:00:00 2001 From: mattijs Date: Wed, 13 Jan 2010 19:06:11 +0000 Subject: [PATCH 010/250] Moved dumping of graph up to ease debugging --- .../scotchDecomp/scotchDecomp.C | 90 +++++++++---------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/src/parallel/decompositionMethods/scotchDecomp/scotchDecomp.C b/src/parallel/decompositionMethods/scotchDecomp/scotchDecomp.C index 5375fb529b..c14e7e39f1 100644 --- a/src/parallel/decompositionMethods/scotchDecomp/scotchDecomp.C +++ b/src/parallel/decompositionMethods/scotchDecomp/scotchDecomp.C @@ -126,6 +126,51 @@ Foam::label Foam::scotchDecomp::decompose List& finalDecomp ) { + // Dump graph + if (decompositionDict_.found("scotchCoeffs")) + { + const dictionary& scotchCoeffs = + decompositionDict_.subDict("scotchCoeffs"); + + if (scotchCoeffs.found("writeGraph")) + { + Switch writeGraph(scotchCoeffs.lookup("writeGraph")); + + if (writeGraph) + { + OFstream str(mesh_.time().path() / mesh_.name() + ".grf"); + + Info<< "Dumping Scotch graph file to " << str.name() << endl + << "Use this in combination with gpart." << endl; + + label version = 0; + str << version << nl; + // Numer of vertices + str << xadj.size()-1 << ' ' << adjncy.size() << nl; + // Numbering starts from 0 + label baseval = 0; + // Has weights? + label hasEdgeWeights = 0; + label hasVertexWeights = 0; + label numericflag = 10*hasEdgeWeights+hasVertexWeights; + str << baseval << ' ' << numericflag << nl; + for (label cellI = 0; cellI < xadj.size()-1; cellI++) + { + label start = xadj[cellI]; + label end = xadj[cellI+1]; + str << end-start; + + for (label i = start; i < end; i++) + { + str << ' ' << adjncy[i]; + } + str << nl; + } + } + } + } + + // Strategy // ~~~~~~~~ @@ -206,51 +251,6 @@ Foam::label Foam::scotchDecomp::decompose check(SCOTCH_graphCheck(&grafdat), "SCOTCH_graphCheck"); - // Dump graph - if (decompositionDict_.found("scotchCoeffs")) - { - const dictionary& scotchCoeffs = - decompositionDict_.subDict("scotchCoeffs"); - - if (scotchCoeffs.found("writeGraph")) - { - Switch writeGraph(scotchCoeffs.lookup("writeGraph")); - - if (writeGraph) - { - OFstream str(mesh_.time().path() / mesh_.name() + ".grf"); - - Info<< "Dumping Scotch graph file to " << str.name() << endl - << "Use this in combination with gpart." << endl; - - label version = 0; - str << version << nl; - // Numer of vertices - str << xadj.size()-1 << ' ' << adjncy.size() << nl; - // Numbering starts from 0 - label baseval = 0; - // Has weights? - label hasEdgeWeights = 0; - label hasVertexWeights = 0; - label numericflag = 10*hasEdgeWeights+hasVertexWeights; - str << baseval << ' ' << numericflag << nl; - for (label cellI = 0; cellI < xadj.size()-1; cellI++) - { - label start = xadj[cellI]; - label end = xadj[cellI+1]; - str << end-start; - - for (label i = start; i < end; i++) - { - str << ' ' << adjncy[i]; - } - str << nl; - } - } - } - } - - // Architecture // ~~~~~~~~~~~~ // (fully connected network topology since using switch) From 735de0c758c6a4be4831a418a2d223dae769a144 Mon Sep 17 00:00:00 2001 From: mattijs Date: Wed, 13 Jan 2010 19:07:04 +0000 Subject: [PATCH 011/250] Assign points even when no merging; remove points used by illegal triangles --- src/triSurface/triSurface/stitchTriangles.C | 93 ++++++++++++++++----- 1 file changed, 72 insertions(+), 21 deletions(-) diff --git a/src/triSurface/triSurface/stitchTriangles.C b/src/triSurface/triSurface/stitchTriangles.C index 7a441ac679..70fe304808 100644 --- a/src/triSurface/triSurface/stitchTriangles.C +++ b/src/triSurface/triSurface/stitchTriangles.C @@ -26,6 +26,7 @@ License #include "triSurface.H" #include "mergePoints.H" +#include "PackedBoolList.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -46,46 +47,44 @@ bool triSurface::stitchTriangles pointField newPoints; bool hasMerged = mergePoints(rawPoints, tol, verbose, pointMap, newPoints); + pointField& ps = storedPoints(); + // Set the coordinates to the merged ones + ps.transfer(newPoints); if (hasMerged) { if (verbose) { Pout<< "stitchTriangles : Merged from " << rawPoints.size() - << " points down to " << newPoints.size() << endl; + << " points down to " << ps.size() << endl; } - pointField& ps = storedPoints(); - - // Set the coordinates to the merged ones - ps = newPoints; - // Reset the triangle point labels to the unique points array label newTriangleI = 0; forAll(*this, i) { - label newA = pointMap[operator[](i)[0]]; - label newB = pointMap[operator[](i)[1]]; - label newC = pointMap[operator[](i)[2]]; + const labelledTri& tri = operator[](i); + labelledTri newTri + ( + pointMap[tri[0]], + pointMap[tri[1]], + pointMap[tri[2]], + tri.region() + ); - if ((newA != newB) && (newA != newC) && (newB != newC)) + if ((newTri[0] != newTri[1]) && (newTri[0] != newTri[2]) && (newTri[1] != newTri[2])) { - operator[](newTriangleI)[0] = newA; - operator[](newTriangleI)[1] = newB; - operator[](newTriangleI)[2] = newC; - operator[](newTriangleI).region() = operator[](i).region(); - newTriangleI++; + operator[](newTriangleI++) = newTri; } else if (verbose) { Pout<< "stitchTriangles : " - << "Removing triangle " << i << " with non-unique vertices." - << endl - << " vertices :" << newA << ' ' << newB << ' ' << newC - << endl - << " coordinates:" << ps[newA] << ' ' << ps[newB] - << ' ' << ps[newC] << endl; + << "Removing triangle " << i + << " with non-unique vertices." << endl + << " vertices :" << newTri << endl + << " coordinates:" << newTri.points(ps) + << endl; } } @@ -98,6 +97,58 @@ bool triSurface::stitchTriangles << " triangles" << endl; } setSize(newTriangleI); + + // And possibly compact out any unused points (since used only + // by triangles that have just been deleted) + // Done in two passes to save memory (pointField) + + // 1. Detect only + PackedBoolList pointIsUsed(ps.size()); + + label nPoints = 0; + + forAll(*this, i) + { + const labelledTri& tri = operator[](i); + + forAll(tri, fp) + { + label pointI = tri[fp]; + if (pointIsUsed.set(pointI, 1)) + { + nPoints++; + } + } + } + + if (nPoints != ps.size()) + { + // 2. Compact. + pointMap.setSize(ps.size()); + label newPointI = 0; + forAll(pointIsUsed, pointI) + { + if (pointIsUsed[pointI]) + { + ps[newPointI] = ps[pointI]; + pointMap[pointI] = newPointI++; + } + } + ps.setSize(newPointI); + + newTriangleI = 0; + forAll(*this, i) + { + const labelledTri& tri = operator[](i); + operator[](newTriangleI++) = labelledTri + ( + pointMap[tri[0]], + pointMap[tri[1]], + pointMap[tri[2]], + tri.region() + ); + } + } } } From 1e78a1486552d9ab5e6c83de2fa4cc2878985038 Mon Sep 17 00:00:00 2001 From: mattijs Date: Wed, 13 Jan 2010 19:08:01 +0000 Subject: [PATCH 012/250] Handle tracking on face or edge --- src/meshTools/indexedOctree/indexedOctree.C | 54 +++++++++++---------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/src/meshTools/indexedOctree/indexedOctree.C b/src/meshTools/indexedOctree/indexedOctree.C index 128e6bf600..1d444eff3d 100644 --- a/src/meshTools/indexedOctree/indexedOctree.C +++ b/src/meshTools/indexedOctree/indexedOctree.C @@ -957,6 +957,7 @@ Foam::point Foam::indexedOctree::pushPointIntoFace } else if (nFaces == 1) { + // Point is on a single face keepFaceID = faceIndices[0]; } else @@ -1782,16 +1783,6 @@ Foam::pointIndexHit Foam::indexedOctree::findLine label i = 0; for (; i < 100000; i++) { - if (verbose) - { - Pout<< "iter:" << i - << " at startPoint:" << hitInfo.rawPoint() << endl - << " node:" << nodeI - << " octant:" << octant - << " bb:" << subBbox(nodeI, octant) << endl; - } - - // Ray-trace to end of current node. Updates point (either on triangle // in case of hit or on node bounding box in case of miss) @@ -1808,6 +1799,19 @@ Foam::pointIndexHit Foam::indexedOctree::findLine ) ); + if (verbose) + { + Pout<< "iter:" << i + << " at current:" << hitInfo.rawPoint() + << " (perturbed:" << startPoint << ")" << endl + << " node:" << nodeI + << " octant:" << octant + << " bb:" << subBbox(nodeI, octant) << endl; + } + + + + // Faces of current bounding box current point is on direction hitFaceID = 0; @@ -1833,12 +1837,23 @@ Foam::pointIndexHit Foam::indexedOctree::findLine break; } - if (hitFaceID == 0) + if (hitFaceID == 0 || hitInfo.rawPoint() == treeEnd) { // endpoint inside the tree. Return miss. break; } + // Create a point on other side of face. + point perturbedPoint + ( + pushPoint + ( + octantBb, + hitFaceID, + hitInfo.rawPoint(), + false // push outside of octantBb + ) + ); if (verbose) { @@ -1848,14 +1863,7 @@ Foam::pointIndexHit Foam::indexedOctree::findLine << " node:" << nodeI << " octant:" << octant << " bb:" << subBbox(nodeI, octant) << nl - << " walking to neighbour containing:" - << pushPoint - ( - octantBb, - hitFaceID, - hitInfo.rawPoint(), - false // push outside of octantBb - ) + << " walking to neighbour containing:" << perturbedPoint << endl; } @@ -1866,13 +1874,7 @@ Foam::pointIndexHit Foam::indexedOctree::findLine bool ok = walkToNeighbour ( - pushPoint - ( - octantBb, - hitFaceID, - hitInfo.rawPoint(), - false // push outside of octantBb - ), + perturbedPoint, hitFaceID, // face(s) that hitInfo is on nodeI, From 0496e181236503bd21f8121bf0dbced60177a514 Mon Sep 17 00:00:00 2001 From: mattijs Date: Wed, 13 Jan 2010 19:08:47 +0000 Subject: [PATCH 013/250] Modified tolerances to take truncation error into account --- .../polyPatches/basic/coupled/coupledPolyPatch.C | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/OpenFOAM/meshes/polyMesh/polyPatches/basic/coupled/coupledPolyPatch.C b/src/OpenFOAM/meshes/polyMesh/polyPatches/basic/coupled/coupledPolyPatch.C index ee2d966836..8e18f68c77 100644 --- a/src/OpenFOAM/meshes/polyMesh/polyPatches/basic/coupled/coupledPolyPatch.C +++ b/src/OpenFOAM/meshes/polyMesh/polyPatches/basic/coupled/coupledPolyPatch.C @@ -199,13 +199,20 @@ Foam::scalarField Foam::coupledPolyPatch::calcFaceTol const face& f = faces[faceI]; + // 1. calculate a typical size of the face. Use maximum distance + // to face centre scalar maxLenSqr = -GREAT; + // 2. as measure of truncation error when comparing two coordinates + // use SMALL * maximum component + scalar maxCmpt = -GREAT; forAll(f, fp) { - maxLenSqr = max(maxLenSqr, magSqr(points[f[fp]] - cc)); + const point& pt = points[f[fp]]; + maxLenSqr = max(maxLenSqr, magSqr(pt - cc)); + maxCmpt = max(maxCmpt, cmptMax(cmptMag(pt))); } - tols[faceI] = matchTol * Foam::sqrt(maxLenSqr); + tols[faceI] = max(SMALL*maxCmpt, matchTol*Foam::sqrt(maxLenSqr)); } return tols; } From 21048d96005bb8371806eaa2ccc93a222a184d78 Mon Sep 17 00:00:00 2001 From: mattijs Date: Wed, 13 Jan 2010 19:10:54 +0000 Subject: [PATCH 014/250] Disabled writing zero-sized faceZones since upset tecio library --- .../foamToTecplot360/foamToTecplot360.C | 145 ++++++++++-------- 1 file changed, 77 insertions(+), 68 deletions(-) diff --git a/applications/utilities/postProcessing/dataConversion/foamToTecplot360/foamToTecplot360.C b/applications/utilities/postProcessing/dataConversion/foamToTecplot360/foamToTecplot360.C index 6c1065a489..44384b7efe 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToTecplot360/foamToTecplot360.C +++ b/applications/utilities/postProcessing/dataConversion/foamToTecplot360/foamToTecplot360.C @@ -1077,83 +1077,92 @@ int main(int argc, char *argv[]) { const faceZone& pp = zones[zoneI]; - const indirectPrimitivePatch ipp - ( - IndirectList(mesh.faces(), pp), - mesh.points() - ); + if (pp.size() > 0) + { + const indirectPrimitivePatch ipp + ( + IndirectList(mesh.faces(), pp), + mesh.points() + ); - writer.writePolygonalZone - ( - pp.name(), - strandID++, //1+patchIDs.size()+zoneI, //strandID, - ipp, - allVarLocation - ); + writer.writePolygonalZone + ( + pp.name(), + strandID++, //1+patchIDs.size()+zoneI, //strandID, + ipp, + allVarLocation + ); - // Write coordinates - writer.writeField(ipp.localPoints().component(0)()); - writer.writeField(ipp.localPoints().component(1)()); - writer.writeField(ipp.localPoints().component(2)()); + // Write coordinates + writer.writeField(ipp.localPoints().component(0)()); + writer.writeField(ipp.localPoints().component(1)()); + writer.writeField(ipp.localPoints().component(2)()); - // Write all volfields - forAll(vsf, i) - { - writer.writeField - ( - writer.getFaceField + // Write all volfields + forAll(vsf, i) + { + writer.writeField ( - linearInterpolate(vsf[i])(), - pp - )() - ); - } - forAll(vvf, i) - { - writer.writeField - ( - writer.getFaceField + writer.getFaceField + ( + linearInterpolate(vsf[i])(), + pp + )() + ); + } + forAll(vvf, i) + { + writer.writeField ( - linearInterpolate(vvf[i])(), - pp - )() - ); - } - forAll(vSpheretf, i) - { - writer.writeField - ( - writer.getFaceField + writer.getFaceField + ( + linearInterpolate(vvf[i])(), + pp + )() + ); + } + forAll(vSpheretf, i) + { + writer.writeField ( - linearInterpolate(vSpheretf[i])(), - pp - )() - ); - } - forAll(vSymmtf, i) - { - writer.writeField - ( - writer.getFaceField + writer.getFaceField + ( + linearInterpolate(vSpheretf[i])(), + pp + )() + ); + } + forAll(vSymmtf, i) + { + writer.writeField ( - linearInterpolate(vSymmtf[i])(), - pp - )() - ); - } - forAll(vtf, i) - { - writer.writeField - ( - writer.getFaceField + writer.getFaceField + ( + linearInterpolate(vSymmtf[i])(), + pp + )() + ); + } + forAll(vtf, i) + { + writer.writeField ( - linearInterpolate(vtf[i])(), - pp - )() - ); - } + writer.getFaceField + ( + linearInterpolate(vtf[i])(), + pp + )() + ); + } - writer.writeConnectivity(ipp); + writer.writeConnectivity(ipp); + } + else + { + Info<< " Skipping zero sized faceZone " << zoneI + << "\t" << pp.name() + << nl << endl; + } } } From e2eab734f8cc76a2ebbddef1ff7d1b100904ef14 Mon Sep 17 00:00:00 2001 From: andy Date: Fri, 15 Jan 2010 11:59:29 +0000 Subject: [PATCH 015/250] Clean-up of patch field default field name I/O --- .../activeBaffleVelocityFvPatchVectorField.C | 32 +++++++++---------- ...MappedVelocityFluxFixedValueFvPatchField.C | 22 ++++++------- .../fixedFluxPressureFvPatchScalarField.C | 15 ++------- ...ureCompressibleDensityFvPatchScalarField.C | 6 ++-- .../fluxCorrectedVelocityFvPatchVectorField.C | 10 ++---- ...OutletTotalTemperatureFvPatchScalarField.C | 17 ++-------- .../movingWallVelocityFvPatchVectorField.C | 22 ++++++++----- .../movingWallVelocityFvPatchVectorField.H | 5 +++ ...tedInletOutletVelocityFvPatchVectorField.C | 10 ++---- ...eDirectedInletVelocityFvPatchVectorField.C | 10 ++---- ...ureInletOutletVelocityFvPatchVectorField.C | 5 +-- .../pressureInletVelocityFvPatchVectorField.C | 10 ++---- ...ngUniformTotalPressureFvPatchScalarField.C | 10 ++---- .../totalTemperatureFvPatchScalarField.C | 17 ++-------- ...sityKineticEnergyInletFvPatchScalarField.C | 8 ++++- ...sityKineticEnergyInletFvPatchScalarField.H | 4 +++ 16 files changed, 80 insertions(+), 123 deletions(-) diff --git a/src/finiteVolume/fields/fvPatchFields/derived/activeBaffleVelocity/activeBaffleVelocityFvPatchVectorField.C b/src/finiteVolume/fields/fvPatchFields/derived/activeBaffleVelocity/activeBaffleVelocityFvPatchVectorField.C index 1e4f3ffcc5..0ef1c8e35a 100644 --- a/src/finiteVolume/fields/fvPatchFields/derived/activeBaffleVelocity/activeBaffleVelocityFvPatchVectorField.C +++ b/src/finiteVolume/fields/fvPatchFields/derived/activeBaffleVelocity/activeBaffleVelocityFvPatchVectorField.C @@ -84,7 +84,7 @@ activeBaffleVelocityFvPatchVectorField ) : fixedValueFvPatchVectorField(p, iF), - pName_("p"), + pName_(dict.lookupOrDefault("p", "p")), cyclicPatchName_(dict.lookup("cyclicPatch")), cyclicPatchLabel_(p.patch().boundaryMesh().findPatchID(cyclicPatchName_)), orientation_(readLabel(dict.lookup("orientation"))), @@ -96,11 +96,6 @@ activeBaffleVelocityFvPatchVectorField curTimeIndex_(-1) { fvPatchVectorField::operator=(vector::zero); - - if (dict.found("p")) - { - dict.lookup("p") >> pName_; - } } @@ -219,15 +214,21 @@ void Foam::activeBaffleVelocityFvPatchVectorField::updateCoeffs() } openFraction_ = - max(min( - openFraction_ - + max + max + ( + min ( - this->db().time().deltaTValue()/openingTime_, - maxOpenFractionDelta_ - ) - *(orientation_*sign(forceDiff)), - 1 - 1e-6), 1e-6); + openFraction_ + + max + ( + this->db().time().deltaTValue()/openingTime_, + maxOpenFractionDelta_ + ) + *(orientation_*sign(forceDiff)), + 1 - 1e-6 + ), + 1e-6 + ); Info<< "openFraction = " << openFraction_ << endl; @@ -264,8 +265,7 @@ void Foam::activeBaffleVelocityFvPatchVectorField::write(Ostream& os) const << maxOpenFractionDelta_ << token::END_STATEMENT << nl; os.writeKeyword("openFraction") << openFraction_ << token::END_STATEMENT << nl; - os.writeKeyword("p") - << pName_ << token::END_STATEMENT << nl; + writeEntryIfDifferent(os, "p", "p", pName_); writeEntry("value", os); } diff --git a/src/finiteVolume/fields/fvPatchFields/derived/directMappedVelocityFluxFixedValue/directMappedVelocityFluxFixedValueFvPatchField.C b/src/finiteVolume/fields/fvPatchFields/derived/directMappedVelocityFluxFixedValue/directMappedVelocityFluxFixedValueFvPatchField.C index 526ee95639..0d1a344e03 100644 --- a/src/finiteVolume/fields/fvPatchFields/derived/directMappedVelocityFluxFixedValue/directMappedVelocityFluxFixedValueFvPatchField.C +++ b/src/finiteVolume/fields/fvPatchFields/derived/directMappedVelocityFluxFixedValue/directMappedVelocityFluxFixedValueFvPatchField.C @@ -46,7 +46,7 @@ directMappedVelocityFluxFixedValueFvPatchField ) : fixedValueFvPatchVectorField(p, iF), - phiName_("undefinedPhi") + phiName_("phi") {} @@ -93,22 +93,22 @@ directMappedVelocityFluxFixedValueFvPatchField ) : fixedValueFvPatchVectorField(p, iF, dict), - phiName_(dict.lookup("phi")) + phiName_(dict.lookupOrDefault("phi", "phi")) { if (!isA(this->patch().patch())) { FatalErrorIn ( "directMappedVelocityFluxFixedValueFvPatchField::" - "directMappedVelocityFluxFixedValueFvPatchField\n" - "(\n" - " const fvPatch& p,\n" - " const DimensionedField& iF,\n" - " const dictionary& dict\n" - ")\n" - ) << "\n patch type '" << p.type() + "directMappedVelocityFluxFixedValueFvPatchField" + "(" + "const fvPatch&, " + "const DimensionedField& iF, " + "const dictionary&" + ")" + ) << "patch type '" << p.type() << "' not type '" << directMappedPatchBase::typeName << "'" - << "\n for patch " << p.name() + << " for patch " << p.name() << " of field " << dimensionedInternalField().name() << " in file " << dimensionedInternalField().objectPath() << exit(FatalError); @@ -274,7 +274,7 @@ void directMappedVelocityFluxFixedValueFvPatchField::updateCoeffs() void directMappedVelocityFluxFixedValueFvPatchField::write(Ostream& os) const { fvPatchVectorField::write(os); - os.writeKeyword("phi") << phiName_ << token::END_STATEMENT << nl; + writeEntryIfDifferent(os, "phi", "phi", phiName_); this->writeEntry("value", os); } diff --git a/src/finiteVolume/fields/fvPatchFields/derived/fixedFluxPressure/fixedFluxPressureFvPatchScalarField.C b/src/finiteVolume/fields/fvPatchFields/derived/fixedFluxPressure/fixedFluxPressureFvPatchScalarField.C index 8c20f2922c..ac55d86ee2 100644 --- a/src/finiteVolume/fields/fvPatchFields/derived/fixedFluxPressure/fixedFluxPressureFvPatchScalarField.C +++ b/src/finiteVolume/fields/fvPatchFields/derived/fixedFluxPressure/fixedFluxPressureFvPatchScalarField.C @@ -161,18 +161,9 @@ void Foam::fixedFluxPressureFvPatchScalarField::updateCoeffs() void Foam::fixedFluxPressureFvPatchScalarField::write(Ostream& os) const { fvPatchScalarField::write(os); - if (UName_ != "U") - { - os.writeKeyword("U") << UName_ << token::END_STATEMENT << nl; - } - if (phiName_ != "phi") - { - os.writeKeyword("phi") << phiName_ << token::END_STATEMENT << nl; - } - if (rhoName_ != "rho") - { - os.writeKeyword("rho") << rhoName_ << token::END_STATEMENT << nl; - } + writeEntryIfDifferent(os, "U", "U", UName_); + writeEntryIfDifferent(os, "phi", "phi", phiName_); + writeEntryIfDifferent(os, "rho", "rho", rhoName_); os.writeKeyword("adjoint") << adjoint_ << token::END_STATEMENT << nl; gradient().writeEntry("gradient", os); } diff --git a/src/finiteVolume/fields/fvPatchFields/derived/fixedPressureCompressibleDensity/fixedPressureCompressibleDensityFvPatchScalarField.C b/src/finiteVolume/fields/fvPatchFields/derived/fixedPressureCompressibleDensity/fixedPressureCompressibleDensityFvPatchScalarField.C index 0f01c960b0..a89929e428 100644 --- a/src/finiteVolume/fields/fvPatchFields/derived/fixedPressureCompressibleDensity/fixedPressureCompressibleDensityFvPatchScalarField.C +++ b/src/finiteVolume/fields/fvPatchFields/derived/fixedPressureCompressibleDensity/fixedPressureCompressibleDensityFvPatchScalarField.C @@ -45,7 +45,7 @@ fixedPressureCompressibleDensityFvPatchScalarField ) : fixedValueFvPatchField(p, iF), - pName_("pNameIsUndefined") + pName_("p") {} @@ -72,7 +72,7 @@ fixedPressureCompressibleDensityFvPatchScalarField ) : fixedValueFvPatchField(p, iF, dict), - pName_(dict.lookup("p")) + pName_(dict.lookupOrDefault("p", "p")) {} @@ -134,7 +134,7 @@ void fixedPressureCompressibleDensityFvPatchScalarField::write ) const { fvPatchField::write(os); - os.writeKeyword("p") << pName_ << token::END_STATEMENT << nl; + writeEntryIfDifferent(os, "p", "p", pName_); writeEntry("value", os); } diff --git a/src/finiteVolume/fields/fvPatchFields/derived/fluxCorrectedVelocity/fluxCorrectedVelocityFvPatchVectorField.C b/src/finiteVolume/fields/fvPatchFields/derived/fluxCorrectedVelocity/fluxCorrectedVelocityFvPatchVectorField.C index 7de0e1f9d8..675762c738 100644 --- a/src/finiteVolume/fields/fvPatchFields/derived/fluxCorrectedVelocity/fluxCorrectedVelocityFvPatchVectorField.C +++ b/src/finiteVolume/fields/fvPatchFields/derived/fluxCorrectedVelocity/fluxCorrectedVelocityFvPatchVectorField.C @@ -143,14 +143,8 @@ void Foam::fluxCorrectedVelocityFvPatchVectorField::evaluate void Foam::fluxCorrectedVelocityFvPatchVectorField::write(Ostream& os) const { fvPatchVectorField::write(os); - if (phiName_ != "phi") - { - os.writeKeyword("phi") << phiName_ << token::END_STATEMENT << nl; - } - if (rhoName_ != "rho") - { - os.writeKeyword("rho") << rhoName_ << token::END_STATEMENT << nl; - } + writeEntryIfDifferent(os, "phi", "phi", phiName_); + writeEntryIfDifferent(os, "rho", "rho", rhoName_); writeEntry("value", os); } diff --git a/src/finiteVolume/fields/fvPatchFields/derived/inletOutletTotalTemperature/inletOutletTotalTemperatureFvPatchScalarField.C b/src/finiteVolume/fields/fvPatchFields/derived/inletOutletTotalTemperature/inletOutletTotalTemperatureFvPatchScalarField.C index d6a83b07cb..1d9141aa10 100644 --- a/src/finiteVolume/fields/fvPatchFields/derived/inletOutletTotalTemperature/inletOutletTotalTemperatureFvPatchScalarField.C +++ b/src/finiteVolume/fields/fvPatchFields/derived/inletOutletTotalTemperature/inletOutletTotalTemperatureFvPatchScalarField.C @@ -30,8 +30,6 @@ License #include "volFields.H" #include "surfaceFields.H" -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::inletOutletTotalTemperatureFvPatchScalarField:: @@ -193,18 +191,9 @@ void Foam::inletOutletTotalTemperatureFvPatchScalarField::write(Ostream& os) const { fvPatchScalarField::write(os); - if (UName_ != "U") - { - os.writeKeyword("U") << UName_ << token::END_STATEMENT << nl; - } - if (phiName_ != "phi") - { - os.writeKeyword("phi") << phiName_ << token::END_STATEMENT << nl; - } - if (phiName_ != "psi") - { - os.writeKeyword("psi") << psiName_ << token::END_STATEMENT << nl; - } + writeEntryIfDifferent(os, "U", "U", UName_); + writeEntryIfDifferent(os, "phi", "phi", phiName_); + writeEntryIfDifferent(os, "psi", "psi", psiName_); os.writeKeyword("gamma") << gamma_ << token::END_STATEMENT << nl; T0_.writeEntry("T0", os); writeEntry("value", os); diff --git a/src/finiteVolume/fields/fvPatchFields/derived/movingWallVelocity/movingWallVelocityFvPatchVectorField.C b/src/finiteVolume/fields/fvPatchFields/derived/movingWallVelocity/movingWallVelocityFvPatchVectorField.C index 9c24dae9cc..ebffe092db 100644 --- a/src/finiteVolume/fields/fvPatchFields/derived/movingWallVelocity/movingWallVelocityFvPatchVectorField.C +++ b/src/finiteVolume/fields/fvPatchFields/derived/movingWallVelocity/movingWallVelocityFvPatchVectorField.C @@ -43,7 +43,8 @@ movingWallVelocityFvPatchVectorField::movingWallVelocityFvPatchVectorField const DimensionedField& iF ) : - fixedValueFvPatchVectorField(p, iF) + fixedValueFvPatchVectorField(p, iF), + UName_("U") {} @@ -55,7 +56,8 @@ movingWallVelocityFvPatchVectorField::movingWallVelocityFvPatchVectorField const fvPatchFieldMapper& mapper ) : - fixedValueFvPatchVectorField(ptf, p, iF, mapper) + fixedValueFvPatchVectorField(ptf, p, iF, mapper), + UName_(ptf.UName_) {} @@ -66,7 +68,8 @@ movingWallVelocityFvPatchVectorField::movingWallVelocityFvPatchVectorField const dictionary& dict ) : - fixedValueFvPatchVectorField(p, iF) + fixedValueFvPatchVectorField(p, iF), + UName_(dict.lookupOrDefault("U", "U")) { fvPatchVectorField::operator=(vectorField("value", dict, p.size())); } @@ -74,20 +77,22 @@ movingWallVelocityFvPatchVectorField::movingWallVelocityFvPatchVectorField movingWallVelocityFvPatchVectorField::movingWallVelocityFvPatchVectorField ( - const movingWallVelocityFvPatchVectorField& pivpvf + const movingWallVelocityFvPatchVectorField& mwvpvf ) : - fixedValueFvPatchVectorField(pivpvf) + fixedValueFvPatchVectorField(mwvpvf), + UName_(mwvpvf.UName_) {} movingWallVelocityFvPatchVectorField::movingWallVelocityFvPatchVectorField ( - const movingWallVelocityFvPatchVectorField& pivpvf, + const movingWallVelocityFvPatchVectorField& mwvpvf, const DimensionedField& iF ) : - fixedValueFvPatchVectorField(pivpvf, iF) + fixedValueFvPatchVectorField(mwvpvf, iF), + UName_(mwvpvf.UName_) {} @@ -114,7 +119,7 @@ void movingWallVelocityFvPatchVectorField::updateCoeffs() vectorField Up = (pp.faceCentres() - oldFc)/mesh.time().deltaTValue(); - const volVectorField& U = db().lookupObject("U"); + const volVectorField& U = db().lookupObject(UName_); scalarField phip = p.patchField(fvc::meshPhi(U)); @@ -132,6 +137,7 @@ void movingWallVelocityFvPatchVectorField::updateCoeffs() void movingWallVelocityFvPatchVectorField::write(Ostream& os) const { fvPatchVectorField::write(os); + writeEntryIfDifferent(os, "U", "U", UName_); writeEntry("value", os); } diff --git a/src/finiteVolume/fields/fvPatchFields/derived/movingWallVelocity/movingWallVelocityFvPatchVectorField.H b/src/finiteVolume/fields/fvPatchFields/derived/movingWallVelocity/movingWallVelocityFvPatchVectorField.H index 11118714be..ba76e373f3 100644 --- a/src/finiteVolume/fields/fvPatchFields/derived/movingWallVelocity/movingWallVelocityFvPatchVectorField.H +++ b/src/finiteVolume/fields/fvPatchFields/derived/movingWallVelocity/movingWallVelocityFvPatchVectorField.H @@ -52,6 +52,11 @@ class movingWallVelocityFvPatchVectorField : public fixedValueFvPatchVectorField { + // Private data + + //- Name of velocity field + word UName_; + public: diff --git a/src/finiteVolume/fields/fvPatchFields/derived/pressureDirectedInletOutletVelocity/pressureDirectedInletOutletVelocityFvPatchVectorField.C b/src/finiteVolume/fields/fvPatchFields/derived/pressureDirectedInletOutletVelocity/pressureDirectedInletOutletVelocityFvPatchVectorField.C index 49923ea891..432a8f0c51 100644 --- a/src/finiteVolume/fields/fvPatchFields/derived/pressureDirectedInletOutletVelocity/pressureDirectedInletOutletVelocityFvPatchVectorField.C +++ b/src/finiteVolume/fields/fvPatchFields/derived/pressureDirectedInletOutletVelocity/pressureDirectedInletOutletVelocityFvPatchVectorField.C @@ -196,14 +196,8 @@ void pressureDirectedInletOutletVelocityFvPatchVectorField:: write(Ostream& os) const { fvPatchVectorField::write(os); - if (phiName_ != "phi") - { - os.writeKeyword("phi") << phiName_ << token::END_STATEMENT << nl; - } - if (rhoName_ != "rho") - { - os.writeKeyword("rho") << rhoName_ << token::END_STATEMENT << nl; - } + writeEntryIfDifferent(os, "phi", "phi", phiName_); + writeEntryIfDifferent(os, "rho", "rho", rhoName_); inletDir_.writeEntry("inletDirection", os); writeEntry("value", os); } diff --git a/src/finiteVolume/fields/fvPatchFields/derived/pressureDirectedInletVelocity/pressureDirectedInletVelocityFvPatchVectorField.C b/src/finiteVolume/fields/fvPatchFields/derived/pressureDirectedInletVelocity/pressureDirectedInletVelocityFvPatchVectorField.C index 287bb5b4b0..af47c95788 100644 --- a/src/finiteVolume/fields/fvPatchFields/derived/pressureDirectedInletVelocity/pressureDirectedInletVelocityFvPatchVectorField.C +++ b/src/finiteVolume/fields/fvPatchFields/derived/pressureDirectedInletVelocity/pressureDirectedInletVelocityFvPatchVectorField.C @@ -184,14 +184,8 @@ void pressureDirectedInletVelocityFvPatchVectorField::updateCoeffs() void pressureDirectedInletVelocityFvPatchVectorField::write(Ostream& os) const { fvPatchVectorField::write(os); - if (phiName_ != "phi") - { - os.writeKeyword("phi") << phiName_ << token::END_STATEMENT << nl; - } - if (rhoName_ != "rho") - { - os.writeKeyword("rho") << rhoName_ << token::END_STATEMENT << nl; - } + writeEntryIfDifferent(os, "phi", "phi", phiName_); + writeEntryIfDifferent(os, "rho", "rho", rhoName_); inletDir_.writeEntry("inletDirection", os); writeEntry("value", os); } diff --git a/src/finiteVolume/fields/fvPatchFields/derived/pressureInletOutletVelocity/pressureInletOutletVelocityFvPatchVectorField.C b/src/finiteVolume/fields/fvPatchFields/derived/pressureInletOutletVelocity/pressureInletOutletVelocityFvPatchVectorField.C index 9b78fe83f8..c4cd883748 100644 --- a/src/finiteVolume/fields/fvPatchFields/derived/pressureInletOutletVelocity/pressureInletOutletVelocityFvPatchVectorField.C +++ b/src/finiteVolume/fields/fvPatchFields/derived/pressureInletOutletVelocity/pressureInletOutletVelocityFvPatchVectorField.C @@ -188,10 +188,7 @@ void pressureInletOutletVelocityFvPatchVectorField::updateCoeffs() void pressureInletOutletVelocityFvPatchVectorField::write(Ostream& os) const { fvPatchVectorField::write(os); - if (phiName_ != "phi") - { - os.writeKeyword("phi") << phiName_ << token::END_STATEMENT << nl; - } + writeEntryIfDifferent(os, "phi", "phi", phiName_); if (tangentialVelocity_.size()) { tangentialVelocity_.writeEntry("tangentialVelocity", os); diff --git a/src/finiteVolume/fields/fvPatchFields/derived/pressureInletVelocity/pressureInletVelocityFvPatchVectorField.C b/src/finiteVolume/fields/fvPatchFields/derived/pressureInletVelocity/pressureInletVelocityFvPatchVectorField.C index d6bcbf8e8d..2c0775523b 100644 --- a/src/finiteVolume/fields/fvPatchFields/derived/pressureInletVelocity/pressureInletVelocityFvPatchVectorField.C +++ b/src/finiteVolume/fields/fvPatchFields/derived/pressureInletVelocity/pressureInletVelocityFvPatchVectorField.C @@ -146,14 +146,8 @@ void pressureInletVelocityFvPatchVectorField::updateCoeffs() void pressureInletVelocityFvPatchVectorField::write(Ostream& os) const { fvPatchVectorField::write(os); - if (phiName_ != "phi") - { - os.writeKeyword("phi") << phiName_ << token::END_STATEMENT << nl; - } - if (rhoName_ != "rho") - { - os.writeKeyword("rho") << rhoName_ << token::END_STATEMENT << nl; - } + writeEntryIfDifferent(os, "phi", "phi", phiName_); + writeEntryIfDifferent(os, "rho", "rho", rhoName_); writeEntry("value", os); } diff --git a/src/finiteVolume/fields/fvPatchFields/derived/timeVaryingUniformTotalPressure/timeVaryingUniformTotalPressureFvPatchScalarField.C b/src/finiteVolume/fields/fvPatchFields/derived/timeVaryingUniformTotalPressure/timeVaryingUniformTotalPressureFvPatchScalarField.C index 1ee28c88a3..ef5a22a6bf 100644 --- a/src/finiteVolume/fields/fvPatchFields/derived/timeVaryingUniformTotalPressure/timeVaryingUniformTotalPressureFvPatchScalarField.C +++ b/src/finiteVolume/fields/fvPatchFields/derived/timeVaryingUniformTotalPressure/timeVaryingUniformTotalPressureFvPatchScalarField.C @@ -218,14 +218,8 @@ void Foam::timeVaryingUniformTotalPressureFvPatchScalarField:: write(Ostream& os) const { fvPatchScalarField::write(os); - if (UName_ != "U") - { - os.writeKeyword("U") << UName_ << token::END_STATEMENT << nl; - } - if (phiName_ != "phi") - { - os.writeKeyword("phi") << phiName_ << token::END_STATEMENT << nl; - } + writeEntryIfDifferent(os, "U", "U", UName_); + writeEntryIfDifferent(os, "phi", "phi", phiName_); os.writeKeyword("rho") << rhoName_ << token::END_STATEMENT << nl; os.writeKeyword("psi") << psiName_ << token::END_STATEMENT << nl; os.writeKeyword("gamma") << gamma_ << token::END_STATEMENT << nl; diff --git a/src/finiteVolume/fields/fvPatchFields/derived/totalTemperature/totalTemperatureFvPatchScalarField.C b/src/finiteVolume/fields/fvPatchFields/derived/totalTemperature/totalTemperatureFvPatchScalarField.C index 402ed3325f..7554aa281d 100644 --- a/src/finiteVolume/fields/fvPatchFields/derived/totalTemperature/totalTemperatureFvPatchScalarField.C +++ b/src/finiteVolume/fields/fvPatchFields/derived/totalTemperature/totalTemperatureFvPatchScalarField.C @@ -30,8 +30,6 @@ License #include "volFields.H" #include "surfaceFields.H" -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::totalTemperatureFvPatchScalarField::totalTemperatureFvPatchScalarField @@ -180,18 +178,9 @@ void Foam::totalTemperatureFvPatchScalarField::updateCoeffs() void Foam::totalTemperatureFvPatchScalarField::write(Ostream& os) const { fvPatchScalarField::write(os); - if (UName_ != "U") - { - os.writeKeyword("U") << UName_ << token::END_STATEMENT << nl; - } - if (phiName_ != "phi") - { - os.writeKeyword("phi") << phiName_ << token::END_STATEMENT << nl; - } - if (psiName_ != "psi") - { - os.writeKeyword("psi") << psiName_ << token::END_STATEMENT << nl; - } + writeEntryIfDifferent(os, "U", "U", UName_); + writeEntryIfDifferent(os, "phi", "phi", phiName_); + writeEntryIfDifferent(os, "psi", "psi", psiName_); os.writeKeyword("gamma") << gamma_ << token::END_STATEMENT << nl; T0_.writeEntry("T0", os); writeEntry("value", os); diff --git a/src/finiteVolume/fields/fvPatchFields/derived/turbulentIntensityKineticEnergyInlet/turbulentIntensityKineticEnergyInletFvPatchScalarField.C b/src/finiteVolume/fields/fvPatchFields/derived/turbulentIntensityKineticEnergyInlet/turbulentIntensityKineticEnergyInletFvPatchScalarField.C index c81934c111..3aa3fccdae 100644 --- a/src/finiteVolume/fields/fvPatchFields/derived/turbulentIntensityKineticEnergyInlet/turbulentIntensityKineticEnergyInletFvPatchScalarField.C +++ b/src/finiteVolume/fields/fvPatchFields/derived/turbulentIntensityKineticEnergyInlet/turbulentIntensityKineticEnergyInletFvPatchScalarField.C @@ -40,6 +40,7 @@ turbulentIntensityKineticEnergyInletFvPatchScalarField ) : fixedValueFvPatchField(p, iF), + UName_("U"), intensity_(0.05) {} @@ -53,6 +54,7 @@ turbulentIntensityKineticEnergyInletFvPatchScalarField ) : fixedValueFvPatchField(ptf, p, iF, mapper), + UName_(ptf.UName_), intensity_(ptf.intensity_) {} @@ -65,6 +67,7 @@ turbulentIntensityKineticEnergyInletFvPatchScalarField ) : fixedValueFvPatchField(p, iF, dict), + UName_(dict.lookupOrDefault("U", "U")), intensity_(readScalar(dict.lookup("intensity"))) { if (intensity_ < 0 || intensity_ > 1) @@ -92,6 +95,7 @@ turbulentIntensityKineticEnergyInletFvPatchScalarField ) : fixedValueFvPatchField(ptf), + UName_(ptf.UName_), intensity_(ptf.intensity_) {} @@ -104,6 +108,7 @@ turbulentIntensityKineticEnergyInletFvPatchScalarField ) : fixedValueFvPatchField(ptf, iF), + UName_(ptf.UName_), intensity_(ptf.intensity_) {} @@ -119,7 +124,7 @@ updateCoeffs() } const fvPatchField& Up = - patch().lookupPatchField("U"); + patch().lookupPatchField(UName_); operator==(1.5*sqr(intensity_)*magSqr(Up)); @@ -133,6 +138,7 @@ void Foam::turbulentIntensityKineticEnergyInletFvPatchScalarField::write ) const { fvPatchField::write(os); + writeEntryIfDifferent(os, "U", "U", UName_); os.writeKeyword("intensity") << intensity_ << token::END_STATEMENT << nl; writeEntry("value", os); } diff --git a/src/finiteVolume/fields/fvPatchFields/derived/turbulentIntensityKineticEnergyInlet/turbulentIntensityKineticEnergyInletFvPatchScalarField.H b/src/finiteVolume/fields/fvPatchFields/derived/turbulentIntensityKineticEnergyInlet/turbulentIntensityKineticEnergyInletFvPatchScalarField.H index 6b4dfdb183..894f2b4520 100644 --- a/src/finiteVolume/fields/fvPatchFields/derived/turbulentIntensityKineticEnergyInlet/turbulentIntensityKineticEnergyInletFvPatchScalarField.H +++ b/src/finiteVolume/fields/fvPatchFields/derived/turbulentIntensityKineticEnergyInlet/turbulentIntensityKineticEnergyInletFvPatchScalarField.H @@ -34,6 +34,7 @@ Description inlet { type turbulentIntensityKineticEnergyInlet; + U U; // Name of U field (optional) intensity 0.05; // 5% turbulence value uniform 1; // placeholder } @@ -64,6 +65,9 @@ class turbulentIntensityKineticEnergyInletFvPatchScalarField { // Private data + //- Name of belocity field + word UName_; + //- Turbulent intensity as fraction of mean velocity scalar intensity_; From 0d49e4711c93023f756d5359fa44d15509ab2a4d Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Fri, 15 Jan 2010 14:35:50 +0100 Subject: [PATCH 016/250] Begin code refactoring of third-party file formats. --- .../foamDebugSwitches/Make/options | 1 + .../surface/surfaceSubset/surfaceSubset.C | 30 +-- .../surface/surfaceSubset/surfaceSubsetDict | 2 +- src/Allwmake | 1 + src/edgeMesh/Make/options | 5 + src/edgeMesh/edgeFormats/nas/NASedgeFormat.C | 28 --- src/edgeMesh/edgeFormats/nas/NASedgeFormat.H | 11 +- .../edgeFormats/starcd/STARCDedgeFormat.C | 128 ------------- .../edgeFormats/starcd/STARCDedgeFormat.H | 13 +- src/fileFormats/Make/files | 4 + src/fileFormats/Make/options | 0 .../nas/NASCore.C} | 13 +- .../nas/NASCore.H} | 32 ++-- src/fileFormats/starcd/STARCDCore.C | 173 ++++++++++++++++++ src/fileFormats/starcd/STARCDCore.H | 131 +++++++++++++ src/surfMesh/Make/files | 1 - src/surfMesh/Make/options | 5 + .../surfaceFormats/nas/NASsurfaceFormat.H | 4 +- .../starcd/STARCDsurfaceFormatCore.C | 140 +------------- .../starcd/STARCDsurfaceFormatCore.H | 11 +- src/triSurface/Make/options | 6 +- 21 files changed, 380 insertions(+), 359 deletions(-) create mode 100644 src/fileFormats/Make/files create mode 100644 src/fileFormats/Make/options rename src/{surfMesh/surfaceFormats/nas/NASsurfaceFormatCore.C => fileFormats/nas/NASCore.C} (87%) rename src/{surfMesh/surfaceFormats/nas/NASsurfaceFormatCore.H => fileFormats/nas/NASCore.H} (81%) create mode 100644 src/fileFormats/starcd/STARCDCore.C create mode 100644 src/fileFormats/starcd/STARCDCore.H diff --git a/applications/utilities/miscellaneous/foamDebugSwitches/Make/options b/applications/utilities/miscellaneous/foamDebugSwitches/Make/options index e473b84bb9..7207b53927 100644 --- a/applications/utilities/miscellaneous/foamDebugSwitches/Make/options +++ b/applications/utilities/miscellaneous/foamDebugSwitches/Make/options @@ -18,6 +18,7 @@ EXE_LIBS = \ -lengine \ -lerrorEstimation \ -lfieldFunctionObjects \ + -lfileFormats \ -lfiniteVolume \ -lforces \ -lfvMotionSolvers \ diff --git a/applications/utilities/surface/surfaceSubset/surfaceSubset.C b/applications/utilities/surface/surfaceSubset/surfaceSubset.C index dd8a6ede00..6cc8ee4678 100644 --- a/applications/utilities/surface/surfaceSubset/surfaceSubset.C +++ b/applications/utilities/surface/surfaceSubset/surfaceSubset.C @@ -100,10 +100,8 @@ int main(int argc, char *argv[]) meshSubsetDict.lookup("addFaceNeighbours") ); - Switch invertSelection - ( - meshSubsetDict.lookup("invertSelection") - ); + const bool invertSelection = + meshSubsetDict.lookupOrDefault("invertSelection", false); // Mark the cells for the subset @@ -246,7 +244,7 @@ int main(int argc, char *argv[]) // bb of surface treeBoundBox bb(selectSurf.localPoints()); - // Radnom number generator + // Random number generator Random rndGen(354543); // search engine @@ -269,14 +267,11 @@ int main(int argc, char *argv[]) indexedOctree::volumeType t = selectTree.getVolumeType(fc); - if (t == indexedOctree::INSIDE && !outside) - { - facesToSubset[faceI] = true; - } - else if + if ( - t == indexedOctree::OUTSIDE - && outside + outside + ? (t == indexedOctree::OUTSIDE) + : (t == indexedOctree::INSIDE) ) { facesToSubset[faceI] = true; @@ -346,20 +341,11 @@ int main(int argc, char *argv[]) if (invertSelection) { Info<< "Inverting selection." << endl; - boolList newFacesToSubset(facesToSubset.size()); forAll(facesToSubset, i) { - if (facesToSubset[i]) - { - newFacesToSubset[i] = false; - } - else - { - newFacesToSubset[i] = true; - } + facesToSubset[i] = facesToSubset[i] ? false : true; } - facesToSubset.transfer(newFacesToSubset); } diff --git a/applications/utilities/surface/surfaceSubset/surfaceSubsetDict b/applications/utilities/surface/surfaceSubset/surfaceSubsetDict index 3a8db2cffd..f956a24789 100644 --- a/applications/utilities/surface/surfaceSubset/surfaceSubsetDict +++ b/applications/utilities/surface/surfaceSubset/surfaceSubsetDict @@ -36,7 +36,7 @@ zone surface { name "sphere.stl"; - outside yes; + outside yes; } // Extend selection with edge neighbours diff --git a/src/Allwmake b/src/Allwmake index a91f131e55..f24f2f370d 100755 --- a/src/Allwmake +++ b/src/Allwmake @@ -22,6 +22,7 @@ wmake libso OpenFOAM wmake libso lagrangian/basic +wmake libso fileFormats wmake libso edgeMesh wmake libso surfMesh wmake libso triSurface diff --git a/src/edgeMesh/Make/options b/src/edgeMesh/Make/options index e69de29bb2..7e207d0dbe 100644 --- a/src/edgeMesh/Make/options +++ b/src/edgeMesh/Make/options @@ -0,0 +1,5 @@ +EXE_INC = \ + -I$(LIB_SRC)/fileFormats/lnInclude + +LIB_LIBS = \ + -lfileFormats diff --git a/src/edgeMesh/edgeFormats/nas/NASedgeFormat.C b/src/edgeMesh/edgeFormats/nas/NASedgeFormat.C index 4b178d1dbd..fec0c883a3 100644 --- a/src/edgeMesh/edgeFormats/nas/NASedgeFormat.C +++ b/src/edgeMesh/edgeFormats/nas/NASedgeFormat.C @@ -29,34 +29,6 @@ License #include "IStringStream.H" #include "PackedBoolList.H" -// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // - -// Do weird things to extract a floating point number -Foam::scalar Foam::fileFormats::NASedgeFormat::parseNASCoord -( - const string& s -) -{ - size_t expSign = s.find_last_of("+-"); - - if (expSign != string::npos && expSign > 0 && !isspace(s[expSign-1])) - { - scalar mantissa = readScalar(IStringStream(s.substr(0, expSign))()); - scalar exponent = readScalar(IStringStream(s.substr(expSign+1))()); - - if (s[expSign] == '-') - { - exponent = -exponent; - } - return mantissa * pow(10, exponent); - } - else - { - return readScalar(IStringStream(s)()); - } -} - - // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::fileFormats::NASedgeFormat::NASedgeFormat diff --git a/src/edgeMesh/edgeFormats/nas/NASedgeFormat.H b/src/edgeMesh/edgeFormats/nas/NASedgeFormat.H index 600b880cb7..3ccd4397af 100644 --- a/src/edgeMesh/edgeFormats/nas/NASedgeFormat.H +++ b/src/edgeMesh/edgeFormats/nas/NASedgeFormat.H @@ -37,6 +37,7 @@ SourceFiles #define NASedgeFormat_H #include "edgeMesh.H" +#include "NASCore.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -51,7 +52,8 @@ namespace fileFormats class NASedgeFormat : - public edgeMesh + public edgeMesh, + public NASCore { // Private Member Functions @@ -61,13 +63,6 @@ class NASedgeFormat //- Disallow default bitwise assignment void operator=(const NASedgeFormat&); -protected: - - // Protected Member Functions - - //- Do weird things to extract number - static scalar parseNASCoord(const string&); - public: // Constructors diff --git a/src/edgeMesh/edgeFormats/starcd/STARCDedgeFormat.C b/src/edgeMesh/edgeFormats/starcd/STARCDedgeFormat.C index b6ecd4d19e..f2fec25cc5 100644 --- a/src/edgeMesh/edgeFormats/starcd/STARCDedgeFormat.C +++ b/src/edgeMesh/edgeFormats/starcd/STARCDedgeFormat.C @@ -59,134 +59,6 @@ inline void Foam::fileFormats::STARCDedgeFormat::writeLines // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // -bool Foam::fileFormats::STARCDedgeFormat::readHeader -( - IFstream& is, - const word& signature -) -{ - if (!is.good()) - { - FatalErrorIn - ( - "fileFormats::STARCDedgeFormat::readHeader(...)" - ) - << "cannot read " << signature << " " << is.name() - << abort(FatalError); - } - - word header; - label majorVersion; - - string line; - - is.getLine(line); - IStringStream(line)() >> header; - - is.getLine(line); - IStringStream(line)() >> majorVersion; - - // add other checks ... - if (header != signature) - { - Info<< "header mismatch " << signature << " " << is.name() - << endl; - } - - return true; -} - - -void Foam::fileFormats::STARCDedgeFormat::writeHeader -( - Ostream& os, - const char* filetype -) -{ - os << "PROSTAR_" << filetype << nl - << 4000 - << " " << 0 - << " " << 0 - << " " << 0 - << " " << 0 - << " " << 0 - << " " << 0 - << " " << 0 - << endl; -} - - -bool Foam::fileFormats::STARCDedgeFormat::readPoints -( - IFstream& is, - pointField& points, - labelList& ids -) -{ - // - // read .vrt file - // ~~~~~~~~~~~~~~ - - if (!is.good()) - { - FatalErrorIn - ( - "fileFormats::STARCDedgeFormat::readPoints(...)" - ) - << "Cannot read file " << is.name() - << exit(FatalError); - } - - readHeader(is, "PROSTAR_VERTEX"); - - DynamicList dynPoints; - DynamicList

specify alternative case directory, default is the cwd + -region specify alternative mesh region + -help print the usage - Remove the contents of the constant/polyMesh directory - as per the Foam::polyMesh::removeFiles() method. +Remove the contents of the constant/polyMesh directory as per the +Foam::polyMesh::removeFiles() method. USAGE exit 1 diff --git a/bin/foamEtcFile b/bin/foamEtcFile index e3faab4121..851ef739b4 100755 --- a/bin/foamEtcFile +++ b/bin/foamEtcFile @@ -3,7 +3,7 @@ # ========= | # \\ / F ield | OpenFOAM: The Open Source CFD Toolbox # \\ / O peration | -# \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd. +# \\ / A nd | Copyright (C) 1991-2010 OpenCFD Ltd. # \\/ M anipulation | #------------------------------------------------------------------------------- # License @@ -40,7 +40,7 @@ usage() { while [ "$#" -ge 1 ]; do echo "$1"; shift; done cat< ... +Usage: ${0##*/} [OPTION] ... options: -v ver specify OpenFOAM version diff --git a/bin/foamJob b/bin/foamJob index 289d430d83..ca51fb6074 100755 --- a/bin/foamJob +++ b/bin/foamJob @@ -3,7 +3,7 @@ # ========= | # \\ / F ield | OpenFOAM: The Open Source CFD Toolbox # \\ / O peration | -# \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd. +# \\ / A nd | Copyright (C) 1991-2010 OpenCFD Ltd. # \\/ M anipulation | #------------------------------------------------------------------------------- # License @@ -33,14 +33,13 @@ usage() { while [ "$#" -ge 1 ]; do echo "$1"; shift; done cat< ... - +Usage: ${0##*/} [OPTION] ... options: - -case dir specify case directory - -s also sends output to screen - -p parallel run of processors - -v ver specify OpenFOAM version - -help this usage + -case specify alternative case directory, default is the cwd + -s also sends output to screen + -p parallel run of processors + -v specify OpenFOAM version + -help print the usage * run an OpenFOAM job in background. Redirects the output to 'log' in the case directory diff --git a/bin/foamNew b/bin/foamNew index d1b31693b9..fde1aa1979 100755 --- a/bin/foamNew +++ b/bin/foamNew @@ -3,7 +3,7 @@ # ========= | # \\ / F ield | OpenFOAM: The Open Source CFD Toolbox # \\ / O peration | -# \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd. +# \\ / A nd | Copyright (C) 1991-2010 OpenCFD Ltd. # \\/ M anipulation | #------------------------------------------------------------------------------- # License @@ -33,7 +33,7 @@ usage() { while [ "$#" -ge 1 ]; do echo "$1"; shift; done cat< {args} +Usage: ${0##*/} {args} * create a new standard OpenFOAM source or template file diff --git a/bin/foamUpdateCaseFileHeader b/bin/foamUpdateCaseFileHeader index cfe611ac81..f72035b134 100755 --- a/bin/foamUpdateCaseFileHeader +++ b/bin/foamUpdateCaseFileHeader @@ -3,7 +3,7 @@ # ========= | # \\ / F ield | OpenFOAM: The Open Source CFD Toolbox # \\ / O peration | -# \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd. +# \\ / A nd | Copyright (C) 1991-2010 OpenCFD Ltd. # \\/ M anipulation | #------------------------------------------------------------------------------ # License @@ -38,7 +38,7 @@ foamVersion=$WM_PROJECT_VERSION usage() { cat< ... +Usage: ${0##*/} [OPTION] ... options: -v VER specifies the version to be written in the header diff --git a/bin/foamUpgradeTurbulenceProperties b/bin/foamUpgradeTurbulenceProperties index 846d8d6cda..517aada23a 100755 --- a/bin/foamUpgradeTurbulenceProperties +++ b/bin/foamUpgradeTurbulenceProperties @@ -3,7 +3,7 @@ # ========= | # \\ / F ield | OpenFOAM: The Open Source CFD Toolbox # \\ / O peration | -# \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd. +# \\ / A nd | Copyright (C) 1991-2010 OpenCFD Ltd. # \\/ M anipulation | #------------------------------------------------------------------------------ # License @@ -39,7 +39,7 @@ usage() { cat< +Usage: ${0##*/} Where is the full path to the turbulenceProperties dictionary diff --git a/bin/paraFoam b/bin/paraFoam index 79bf6506d4..623030e167 100755 --- a/bin/paraFoam +++ b/bin/paraFoam @@ -3,7 +3,7 @@ # ========= | # \\ / F ield | OpenFOAM: The Open Source CFD Toolbox # \\ / O peration | -# \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd. +# \\ / A nd | Copyright (C) 1991-2010 OpenCFD Ltd. # \\/ M anipulation | #------------------------------------------------------------------------------- # License @@ -30,18 +30,21 @@ # start paraview with the OpenFOAM libraries # # Note -# combining -block and -region options yields undefined behaviour +# combining -block or -builtin options with the -region option yields +# undefined behaviour #------------------------------------------------------------------------------ usage() { while [ "$#" -ge 1 ]; do echo "$1"; shift; done cat< specify alternative case directory, default is the cwd + -region specify alternative mesh region + -touch only create the file (eg, .blockMesh, .OpenFOAM, etc) + -help print the usage * start paraview $ParaView_VERSION with the OpenFOAM libraries @@ -52,7 +55,7 @@ USAGE unset regionName touchOnly # reader extension -reader=OpenFOAM +extension=OpenFOAM # parse options while [ "$#" -gt 0 ] @@ -62,7 +65,11 @@ do usage ;; -block | -blockMesh) - reader=blockMesh + extension=blockMesh + shift + ;; + -builtin) + extension=foam shift ;; -case) @@ -87,12 +94,12 @@ done # get a sensible caseName from the directory name caseName=${PWD##*/} -caseFile="$caseName.$reader" +caseFile="$caseName.$extension" fvControls="system" if [ -n "$regionName" ] then - caseFile="$caseName{$regionName}.$reader" + caseFile="$caseName{$regionName}.$extension" fvControls="$fvControls/$regionName" fi @@ -113,7 +120,7 @@ esac # # check existence of essential files # -case $reader in +case $extension in blockMesh) for check in system/controlDict constant/polyMesh/blockMeshDict do @@ -121,7 +128,7 @@ blockMesh) done ;; -OpenFOAM) +builtin | OpenFOAM) for check in system/controlDict $fvControls/fvSchemes $fvControls/fvSolution do [ -s "$parentDir/$check" ] || usage "file does not exist: '$parentDir/$check'" diff --git a/bin/rmdepall b/bin/rmdepall index 5850692d22..f70b76adff 100755 --- a/bin/rmdepall +++ b/bin/rmdepall @@ -3,7 +3,7 @@ # ========= | # \\ / F ield | OpenFOAM: The Open Source CFD Toolbox # \\ / O peration | -# \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd. +# \\ / A nd | Copyright (C) 1991-2010 OpenCFD Ltd. # \\/ M anipulation | #------------------------------------------------------------------------------- # License @@ -32,7 +32,7 @@ usage() { while [ "$#" -ge 1 ]; do echo "$1"; shift; done cat<&2 -usage: ${0##*/} [file] +Usage: ${0##*/} [file] Remove all .dep files or remove .dep files referring to diff --git a/bin/templates/foamScript b/bin/templates/foamScript index e8a160860c..a7fe586512 100644 --- a/bin/templates/foamScript +++ b/bin/templates/foamScript @@ -3,7 +3,7 @@ # ========= | # \\ / F ield | OpenFOAM: The Open Source CFD Toolbox # \\ / O peration | -# \\ / A nd | Copyright (C) 2009-2009 OpenCFD Ltd. +# \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. # \\/ M anipulation | #------------------------------------------------------------------------------ # License diff --git a/bin/templates/source/_Template.C b/bin/templates/source/_Template.C index a45d3ff6ac..5431e02d99 100644 --- a/bin/templates/source/_Template.C +++ b/bin/templates/source/_Template.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2009-2009 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License diff --git a/bin/templates/source/_Template.H b/bin/templates/source/_Template.H index b86edcbde9..1c04fa543d 100644 --- a/bin/templates/source/_Template.H +++ b/bin/templates/source/_Template.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2009-2009 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License diff --git a/bin/templates/source/_TemplateApp.C b/bin/templates/source/_TemplateApp.C index 42f2df0db8..50cd2827ab 100644 --- a/bin/templates/source/_TemplateApp.C +++ b/bin/templates/source/_TemplateApp.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2009-2009 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License diff --git a/bin/templates/source/_TemplateI.H b/bin/templates/source/_TemplateI.H index 10e8e4fec8..cfc30ed48a 100644 --- a/bin/templates/source/_TemplateI.H +++ b/bin/templates/source/_TemplateI.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2009-2009 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License diff --git a/bin/templates/source/_TemplateIO.C b/bin/templates/source/_TemplateIO.C index c6d595100a..8282a55f49 100644 --- a/bin/templates/source/_TemplateIO.C +++ b/bin/templates/source/_TemplateIO.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2009-2009 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License diff --git a/bin/templates/source/foamNewSource b/bin/templates/source/foamNewSource index ec1ad7b2e1..8924b09448 100755 --- a/bin/templates/source/foamNewSource +++ b/bin/templates/source/foamNewSource @@ -3,7 +3,7 @@ # ========= | # \\ / F ield | OpenFOAM: The Open Source CFD Toolbox # \\ / O peration | -# \\ / A nd | Copyright (C) 2009-2009 OpenCFD Ltd. +# \\ / A nd | Copyright (C) 2009-2010 OpenCFD Ltd. # \\/ M anipulation | #------------------------------------------------------------------------------- # License @@ -36,7 +36,7 @@ Template="$WM_PROJECT_DIR/bin/templates/source/_Template" usage() { while [ "$#" -ge 1 ]; do echo "$1"; shift; done cat< +Usage: $Script * create a new standard OpenFOAM source file diff --git a/bin/templates/sourceTemplate/_TemplateTemplate.C b/bin/templates/sourceTemplate/_TemplateTemplate.C index c73d5043a1..21ce4f1b36 100644 --- a/bin/templates/sourceTemplate/_TemplateTemplate.C +++ b/bin/templates/sourceTemplate/_TemplateTemplate.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2009-2009 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License diff --git a/bin/templates/sourceTemplate/_TemplateTemplate.H b/bin/templates/sourceTemplate/_TemplateTemplate.H index 6e24ddda2a..6ee6474936 100644 --- a/bin/templates/sourceTemplate/_TemplateTemplate.H +++ b/bin/templates/sourceTemplate/_TemplateTemplate.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2009-2009 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License diff --git a/bin/templates/sourceTemplate/_TemplateTemplateI.H b/bin/templates/sourceTemplate/_TemplateTemplateI.H index 10e8e4fec8..cfc30ed48a 100644 --- a/bin/templates/sourceTemplate/_TemplateTemplateI.H +++ b/bin/templates/sourceTemplate/_TemplateTemplateI.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2009-2009 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License diff --git a/bin/templates/sourceTemplate/_TemplateTemplateIO.C b/bin/templates/sourceTemplate/_TemplateTemplateIO.C index 9453630b68..d874b91170 100644 --- a/bin/templates/sourceTemplate/_TemplateTemplateIO.C +++ b/bin/templates/sourceTemplate/_TemplateTemplateIO.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2009-2009 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License diff --git a/bin/templates/sourceTemplate/foamNewTemplate b/bin/templates/sourceTemplate/foamNewTemplate index edf4fd3bce..8045a5cac6 100755 --- a/bin/templates/sourceTemplate/foamNewTemplate +++ b/bin/templates/sourceTemplate/foamNewTemplate @@ -3,7 +3,7 @@ # ========= | # \\ / F ield | OpenFOAM: The Open Source CFD Toolbox # \\ / O peration | -# \\ / A nd | Copyright (C) 2009-2009 OpenCFD Ltd. +# \\ / A nd | Copyright (C) 2009-2010 OpenCFD Ltd. # \\/ M anipulation | #------------------------------------------------------------------------------- # License @@ -37,7 +37,7 @@ usage() { while [ "$#" -ge 1 ]; do echo "$1"; shift; done cat<