From a820021a0a0ad80faeff137a294e25bcfec6e95a Mon Sep 17 00:00:00 2001 From: graham Date: Sun, 6 Dec 2009 12:20:38 +0000 Subject: [PATCH 01/14] 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 c194087671abf76111fb6142bbc509cd88728dfb Mon Sep 17 00:00:00 2001 From: graham Date: Mon, 25 Jan 2010 18:35:53 +0000 Subject: [PATCH 02/14] In: src/postProcessing/functionObjects/forces, adding mechanisms for restraints and constraints. Moving sixDoFRigidBodyMotion back one directory. Adding uncoupledSixDoFRigidBodyDisplacement to execute motion specified by the six DoF motion state, but not applying surface forces. Useful for pre-displacing a mesh. Adding constrainedSixDoFRigidBodyDisplacement to temporarily perform Vorticity's lander simulation. Will be removed when generalised constraints are added. --- .../functionObjects/forces/Make/files | 19 +- ...gidBodyDisplacementPointPatchVectorField.C | 206 ++++++++++++++++++ ...gidBodyDisplacementPointPatchVectorField.H | 157 +++++++++++++ ...gidBodyDisplacementPointPatchVectorField.C | 20 ++ .../sixDoFRigidBodyMotion.C | 95 ++++++-- .../sixDoFRigidBodyMotion.H | 46 +++- .../sixDoFRigidBodyMotionI.H | 9 +- .../sixDoFRigidBodyMotionIO.C | 0 .../linearSpring/linearSpring.C | 87 ++++++++ .../linearSpring/linearSpring.H | 121 ++++++++++ .../newSixDoFRigidBodyMotionRestraint.C | 65 ++++++ .../sixDoFRigidBodyMotionRestraint.C | 72 ++++++ .../sixDoFRigidBodyMotionRestraint.H | 133 +++++++++++ .../sixDoFRigidBodyMotionState.C | 0 .../sixDoFRigidBodyMotionState.H | 0 .../sixDoFRigidBodyMotionStateI.H | 0 .../sixDoFRigidBodyMotionStateIO.C | 0 ...gidBodyDisplacementPointPatchVectorField.C | 163 ++++++++++++++ ...gidBodyDisplacementPointPatchVectorField.H | 158 ++++++++++++++ 19 files changed, 1325 insertions(+), 26 deletions(-) create mode 100644 src/postProcessing/functionObjects/forces/pointPatchFields/derived/constrainedSixDoFRigidBodyDisplacement/constrainedSixDoFRigidBodyDisplacementPointPatchVectorField.C create mode 100644 src/postProcessing/functionObjects/forces/pointPatchFields/derived/constrainedSixDoFRigidBodyDisplacement/constrainedSixDoFRigidBodyDisplacementPointPatchVectorField.H rename src/postProcessing/functionObjects/forces/pointPatchFields/derived/{sixDoFRigidBodyDisplacement => }/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C (76%) rename src/postProcessing/functionObjects/forces/pointPatchFields/derived/{sixDoFRigidBodyDisplacement => }/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.H (81%) rename src/postProcessing/functionObjects/forces/pointPatchFields/derived/{sixDoFRigidBodyDisplacement => }/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionI.H (96%) rename src/postProcessing/functionObjects/forces/pointPatchFields/derived/{sixDoFRigidBodyDisplacement => }/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionIO.C (100%) create mode 100644 src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSpring/linearSpring.C create mode 100644 src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSpring/linearSpring.H create mode 100644 src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/newSixDoFRigidBodyMotionRestraint.C create mode 100644 src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.C create mode 100644 src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.H rename src/postProcessing/functionObjects/forces/pointPatchFields/derived/{sixDoFRigidBodyDisplacement => }/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionState.C (100%) rename src/postProcessing/functionObjects/forces/pointPatchFields/derived/{sixDoFRigidBodyDisplacement => }/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionState.H (100%) rename src/postProcessing/functionObjects/forces/pointPatchFields/derived/{sixDoFRigidBodyDisplacement => }/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionStateI.H (100%) rename src/postProcessing/functionObjects/forces/pointPatchFields/derived/{sixDoFRigidBodyDisplacement => }/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionStateIO.C (100%) create mode 100644 src/postProcessing/functionObjects/forces/pointPatchFields/derived/uncoupledSixDoFRigidBodyDisplacement/uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField.C create mode 100644 src/postProcessing/functionObjects/forces/pointPatchFields/derived/uncoupledSixDoFRigidBodyDisplacement/uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField.H diff --git a/src/postProcessing/functionObjects/forces/Make/files b/src/postProcessing/functionObjects/forces/Make/files index 511568cab1..66f3c0a8ec 100644 --- a/src/postProcessing/functionObjects/forces/Make/files +++ b/src/postProcessing/functionObjects/forces/Make/files @@ -4,10 +4,21 @@ forces/forcesFunctionObject.C forceCoeffs/forceCoeffs.C forceCoeffs/forceCoeffsFunctionObject.C +sDoFRBM = pointPatchFields/derived/sixDoFRigidBodyMotion + +$(sDoFRBM)/sixDoFRigidBodyMotion.C +$(sDoFRBM)/sixDoFRigidBodyMotionIO.C +$(sDoFRBM)/sixDoFRigidBodyMotionState.C +$(sDoFRBM)/sixDoFRigidBodyMotionStateIO.C + +sDoFRBMR = $(sDoFRBM)/sixDoFRigidBodyMotionRestraint + +$(sDoFRBMR)/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.C +$(sDoFRBMR)/sixDoFRigidBodyMotionRestraint/newSixDoFRigidBodyMotionRestraint.C +$(sDoFRBMR)/linearSpring/linearSpring.C + pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyDisplacementPointPatchVectorField.C -pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C -pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionIO.C -pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionState.C -pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionStateIO.C +pointPatchFields/derived/uncoupledSixDoFRigidBodyDisplacement/uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField.C +pointPatchFields/derived/constrainedSixDoFRigidBodyDisplacement/constrainedSixDoFRigidBodyDisplacementPointPatchVectorField.C LIB = $(FOAM_LIBBIN)/libforces diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/constrainedSixDoFRigidBodyDisplacement/constrainedSixDoFRigidBodyDisplacementPointPatchVectorField.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/constrainedSixDoFRigidBodyDisplacement/constrainedSixDoFRigidBodyDisplacementPointPatchVectorField.C new file mode 100644 index 0000000000..a1516d15a2 --- /dev/null +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/constrainedSixDoFRigidBodyDisplacement/constrainedSixDoFRigidBodyDisplacementPointPatchVectorField.C @@ -0,0 +1,206 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-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 + +\*---------------------------------------------------------------------------*/ + +#include "constrainedSixDoFRigidBodyDisplacementPointPatchVectorField.H" +#include "pointPatchFields.H" +#include "addToRunTimeSelectionTable.H" +#include "Time.H" +#include "fvMesh.H" +#include "volFields.H" +#include "uniformDimensionedFields.H" +#include "forces.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +constrainedSixDoFRigidBodyDisplacementPointPatchVectorField:: +constrainedSixDoFRigidBodyDisplacementPointPatchVectorField +( + const pointPatch& p, + const DimensionedField& iF +) +: + fixedValuePointPatchField(p, iF), + motion_(), + p0_(p.localPoints()), + rhoInf_(1.0) +{} + + +constrainedSixDoFRigidBodyDisplacementPointPatchVectorField:: +constrainedSixDoFRigidBodyDisplacementPointPatchVectorField +( + const pointPatch& p, + const DimensionedField& iF, + const dictionary& dict +) +: + fixedValuePointPatchField(p, iF, dict), + motion_(dict), + rhoInf_(readScalar(dict.lookup("rhoInf"))) +{ + if (!dict.found("value")) + { + updateCoeffs(); + } + + if (dict.found("p0")) + { + p0_ = vectorField("p0", dict , p.size()); + } + else + { + p0_ = p.localPoints(); + } +} + + +constrainedSixDoFRigidBodyDisplacementPointPatchVectorField:: +constrainedSixDoFRigidBodyDisplacementPointPatchVectorField +( + const constrainedSixDoFRigidBodyDisplacementPointPatchVectorField& ptf, + const pointPatch& p, + const DimensionedField& iF, + const pointPatchFieldMapper& mapper +) +: + fixedValuePointPatchField(ptf, p, iF, mapper), + motion_(ptf.motion_), + p0_(ptf.p0_, mapper), + rhoInf_(ptf.rhoInf_) +{} + + +constrainedSixDoFRigidBodyDisplacementPointPatchVectorField:: +constrainedSixDoFRigidBodyDisplacementPointPatchVectorField +( + const constrainedSixDoFRigidBodyDisplacementPointPatchVectorField& ptf, + const DimensionedField& iF +) +: + fixedValuePointPatchField(ptf, iF), + motion_(ptf.motion_), + p0_(ptf.p0_), + rhoInf_(ptf.rhoInf_) +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void constrainedSixDoFRigidBodyDisplacementPointPatchVectorField::updateCoeffs() +{ + if (this->updated()) + { + return; + } + + const polyMesh& mesh = this->dimensionedInternalField().mesh()(); + const Time& t = mesh.time(); + const pointPatch& ptPatch = this->patch(); + + // Patch force data is valid for the current positions, so + // calculate the forces on the motion object from this data, then + // update the positions + + motion_.updatePosition(t.deltaTValue()); + + dictionary forcesDict; + + forcesDict.add("patches", wordList(1, ptPatch.name())); + forcesDict.add("rhoInf", rhoInf_); + forcesDict.add("CofR", motion_.centreOfMass()); + + forces f("forces", db(), forcesDict); + + forces::forcesMoments fm = f.calcForcesMoment(); + + // Get the forces on the patch faces at the current positions + + vector gravity = vector::zero; + + if (db().foundObject("g")) + { + uniformDimensionedVectorField g = + db().lookupObject("g"); + + gravity = g.value(); + } + + vector rotationAxis(0, 1, 0); + + vector torque + ( + ( + (fm.second().first() + fm.second().second()) + & rotationAxis + ) + *rotationAxis + ); + + motion_.updateForce + ( + vector::zero, // Force no centre of mass motion + torque, // Only rotation allowed around the unit rotationAxis + t.deltaTValue() + ); + + Field::operator=(motion_.generatePositions(p0_) - p0_); + + fixedValuePointPatchField::updateCoeffs(); +} + + +void constrainedSixDoFRigidBodyDisplacementPointPatchVectorField::write +( + Ostream& os +) const +{ + pointPatchField::write(os); + motion_.write(os); + os.writeKeyword("rhoInf") + << rhoInf_ << token::END_STATEMENT << nl; + p0_.writeEntry("p0", os); + writeEntry("value", os); +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +makePointPatchTypeField +( + pointPatchVectorField, + constrainedSixDoFRigidBodyDisplacementPointPatchVectorField +); + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// ************************************************************************* // diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/constrainedSixDoFRigidBodyDisplacement/constrainedSixDoFRigidBodyDisplacementPointPatchVectorField.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/constrainedSixDoFRigidBodyDisplacement/constrainedSixDoFRigidBodyDisplacementPointPatchVectorField.H new file mode 100644 index 0000000000..a17b9aa20c --- /dev/null +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/constrainedSixDoFRigidBodyDisplacement/constrainedSixDoFRigidBodyDisplacementPointPatchVectorField.H @@ -0,0 +1,157 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-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 + Foam::constrainedSixDoFRigidBodyDisplacementPointPatchVectorField + +Description + Foam::constrainedSixDoFRigidBodyDisplacementPointPatchVectorField + +SourceFiles + constrainedSixDoFRigidBodyDisplacementPointPatchVectorField.C + +\*---------------------------------------------------------------------------*/ + +#ifndef constrainedSixDoFRigidBodyDisplacementPointPatchVectorField_H +#define constrainedSixDoFRigidBodyDisplacementPointPatchVectorField_H + +#include "fixedValuePointPatchField.H" +#include "sixDoFRigidBodyMotion.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class constrainedSixDoFRigidBodyDisplacementPointPatchVectorField Declaration +\*---------------------------------------------------------------------------*/ + +class constrainedSixDoFRigidBodyDisplacementPointPatchVectorField +: + public fixedValuePointPatchField +{ + // Private data + + //- Six dof motion object + sixDoFRigidBodyMotion motion_; + + //- Reference positions of points on the patch + pointField p0_; + + //- Reference density required by the forces object for + // incompressible calculations + scalar rhoInf_; + + +public: + + //- Runtime type information + TypeName("constrainedSixDoFRigidBodyDisplacement"); + + + // Constructors + + //- Construct from patch and internal field + constrainedSixDoFRigidBodyDisplacementPointPatchVectorField + ( + const pointPatch&, + const DimensionedField& + ); + + //- Construct from patch, internal field and dictionary + constrainedSixDoFRigidBodyDisplacementPointPatchVectorField + ( + const pointPatch&, + const DimensionedField&, + const dictionary& + ); + + //- Construct by mapping given patchField onto a new patch + constrainedSixDoFRigidBodyDisplacementPointPatchVectorField + ( + const constrainedSixDoFRigidBodyDisplacementPointPatchVectorField&, + const pointPatch&, + const DimensionedField&, + const pointPatchFieldMapper& + ); + + //- Construct and return a clone + virtual autoPtr > clone() const + { + return autoPtr > + ( + new constrainedSixDoFRigidBodyDisplacementPointPatchVectorField + ( + *this + ) + ); + } + + //- Construct as copy setting internal field reference + constrainedSixDoFRigidBodyDisplacementPointPatchVectorField + ( + const constrainedSixDoFRigidBodyDisplacementPointPatchVectorField&, + const DimensionedField& + ); + + //- Construct and return a clone setting internal field reference + virtual autoPtr > clone + ( + const DimensionedField& iF + ) const + { + return autoPtr > + ( + new constrainedSixDoFRigidBodyDisplacementPointPatchVectorField + ( + *this, + iF + ) + ); + } + + + // Member functions + + // Evaluation functions + + //- Update the coefficients associated with the patch field + virtual void updateCoeffs(); + + + //- Write + virtual void write(Ostream&) const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyDisplacementPointPatchVectorField.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyDisplacementPointPatchVectorField.C index 8fb0408e67..660ccb056b 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyDisplacementPointPatchVectorField.C +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyDisplacementPointPatchVectorField.C @@ -160,6 +160,26 @@ void sixDoFRigidBodyDisplacementPointPatchVectorField::updateCoeffs() t.deltaTValue() ); + // ---------------------------------------- + // vector rotationAxis(0, 1, 0); + + // vector torque + // ( + // ( + // (fm.second().first() + fm.second().second()) + // & rotationAxis + // ) + // *rotationAxis + // ); + + // motion_.updateForce + // ( + // vector::zero, // Force no centre of mass motion + // torque, // Only rotation allowed around the unit rotationAxis + // t.deltaTValue() + // ); + // ---------------------------------------- + Field::operator=(motion_.generatePositions(p0_) - p0_); fixedValuePointPatchField::updateCoeffs(); diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C similarity index 76% rename from src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C rename to src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C index dae1ba9f3d..39dafe9a06 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C @@ -26,11 +26,29 @@ License #include "sixDoFRigidBodyMotion.H" +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::sixDoFRigidBodyMotion::applyRestraints() +{ + forAll(restraints_, rI) + { + restraints_[rI].restraintForce(); + } +} + + +void Foam::sixDoFRigidBodyMotion::applyConstraints() +{ + +} + + // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::sixDoFRigidBodyMotion::sixDoFRigidBodyMotion() : motionState_(), + restraints_(), refCentreOfMass_(vector::zero), momentOfInertia_(diagTensor::one*VSMALL), mass_(VSMALL) @@ -59,6 +77,7 @@ Foam::sixDoFRigidBodyMotion::sixDoFRigidBodyMotion pi, tau ), + restraints_(), refCentreOfMass_(refCentreOfMass), momentOfInertia_(momentOfInertia), mass_(mass) @@ -68,10 +87,15 @@ Foam::sixDoFRigidBodyMotion::sixDoFRigidBodyMotion Foam::sixDoFRigidBodyMotion::sixDoFRigidBodyMotion(const dictionary& dict) : motionState_(dict), + restraints_(), refCentreOfMass_(dict.lookupOrDefault("refCentreOfMass", centreOfMass())), momentOfInertia_(dict.lookup("momentOfInertia")), mass_(readScalar(dict.lookup("mass"))) -{} +{ + addRestraints(dict); + + addConstraints(dict); +} Foam::sixDoFRigidBodyMotion::sixDoFRigidBodyMotion @@ -80,6 +104,7 @@ Foam::sixDoFRigidBodyMotion::sixDoFRigidBodyMotion ) : motionState_(sDoFRBM.motionState()), + restraints_(sDoFRBM.restraints()), refCentreOfMass_(sDoFRBM.refCentreOfMass()), momentOfInertia_(sDoFRBM.momentOfInertia()), mass_(sDoFRBM.mass()) @@ -94,6 +119,49 @@ Foam::sixDoFRigidBodyMotion::~sixDoFRigidBodyMotion() // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // +void Foam::sixDoFRigidBodyMotion::addRestraints +( + const dictionary& dict +) +{ + if (dict.found("restraints")) + { + const dictionary& restraintDict = dict.subDict("restraints"); + + label i = 0; + + restraints_.setSize(restraintDict.size()); + + forAllConstIter(IDLList, restraintDict, iter) + { + if (iter().isDict()) + { + Info<< "Adding restraint: " << iter().keyword() << endl; + + restraints_.set + ( + i, + sixDoFRigidBodyMotionRestraint::New(iter().dict()) + ); + } + + i++; + } + + restraints_.setSize(i); + } +} + + +void Foam::sixDoFRigidBodyMotion::addConstraints +( + const dictionary& dict +) +{ + +} + + void Foam::sixDoFRigidBodyMotion::updatePosition ( scalar deltaT @@ -149,7 +217,7 @@ void Foam::sixDoFRigidBodyMotion::updateForce ) { // Second leapfrog velocity adjust part, required after motion and - // force calculation part + // force calculation if (Pstream::master()) { @@ -157,6 +225,10 @@ void Foam::sixDoFRigidBodyMotion::updateForce tau() = (Q().T() & tauGlobal); + applyRestraints(); + + applyConstraints(); + v() += 0.5*deltaT*a(); pi() += 0.5*deltaT*tau(); @@ -173,30 +245,23 @@ void Foam::sixDoFRigidBodyMotion::updateForce scalar deltaT ) { - // Second leapfrog velocity adjust part, required after motion and - // force calculation part + vector a = vector::zero; + + vector tau = vector::zero; if (Pstream::master()) { - a() = vector::zero; - - tau() = vector::zero; - forAll(positions, i) { const vector& f = forces[i]; - a() += f/mass_; + a += f/mass_; - tau() += (positions[i] ^ (Q().T() & f)); + tau += (positions[i] ^ (Q().T() & f)); } - - v() += 0.5*deltaT*a(); - - pi() += 0.5*deltaT*tau(); } - Pstream::scatter(motionState_); + updateForce(a, tau, deltaT); } diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.H similarity index 81% rename from src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.H rename to src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.H index 16ea1d42b2..2a4efa52bb 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.H +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.H @@ -26,10 +26,10 @@ Class Foam::sixDoFRigidBodyMotion Description - Six degree of freedom motion for a rigid body. Angular momentum stored in - body fixed reference frame. Reference orientation of the body must align - with the cartesian axes such that the Inertia tensor is in principle - component form. + Six degree of freedom motion for a rigid body. Angular momentum + stored in body fixed reference frame. Reference orientation of + the body (where Q = I) must align with the cartesian axes such + that the Inertia tensor is in principle component form. Symplectic motion as per: @@ -43,6 +43,9 @@ Description url = {http://link.aip.org/link/?JCP/107/5840/1}, doi = {10.1063/1.474310} + Can add restraints (i.e. a spring) and constraints (i.e. motion + may only be on a plane). + SourceFiles sixDoFRigidBodyMotionI.H sixDoFRigidBodyMotion.C @@ -55,6 +58,8 @@ SourceFiles #include "sixDoFRigidBodyMotionState.H" #include "pointField.H" +#include "sixDoFRigidBodyMotionRestraint.H" + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -79,9 +84,15 @@ class sixDoFRigidBodyMotion { // Private data - // state data object + //- Motion state data object sixDoFRigidBodyMotionState motionState_; + //- Restraints on the motion + PtrList restraints_; + + // //- Constaints on the motion + // PtrList constraints_; + //- Centre of mass of reference state point refCentreOfMass_; @@ -106,6 +117,12 @@ class sixDoFRigidBodyMotion // frame z-axis by the given angle inline tensor rotationTensorZ(scalar deltaT) const; + //- Apply the restraints to the object + void applyRestraints(); + + //- Apply the constraints to the object + void applyConstraints(); + public: @@ -141,11 +158,23 @@ public: // Member Functions + //- Add restraints to the motion, public to allow external + // addition of restraints after construction + void addRestraints(const dictionary& dict); + + //- Add restraints to the motion, public to allow external + // addition of restraints after construction + void addConstraints(const dictionary& dict); + + //- First leapfrog velocity adjust and motion part, required + // before force calculation void updatePosition ( scalar deltaT ); + //- Second leapfrog velocity adjust part, required after motion and + // force calculation void updateForce ( const vector& fGlobal, @@ -153,6 +182,8 @@ public: scalar deltaT ); + //- Global forces supplied at locations, calculating net force + // and moment void updateForce ( const pointField& positions, @@ -160,6 +191,7 @@ public: scalar deltaT ); + //- Transform the given pointField by the current motion state tmp generatePositions(const pointField& pts) const; // Access @@ -167,6 +199,10 @@ public: //- Return access to the motion state inline const sixDoFRigidBodyMotionState& motionState() const; + //- Return access to the restraints + inline const PtrList& + restraints() const; + //- Return access to the centre of mass inline const point& centreOfMass() const; diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionI.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionI.H similarity index 96% rename from src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionI.H rename to src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionI.H index aeb75bdea4..835dbe5c8a 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionI.H +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionI.H @@ -24,8 +24,6 @@ License \*---------------------------------------------------------------------------*/ -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // inline Foam::tensor @@ -71,6 +69,13 @@ Foam::sixDoFRigidBodyMotion::motionState() const } +inline const Foam::PtrList& +Foam::sixDoFRigidBodyMotion::restraints() const +{ + return restraints_; +} + + inline const Foam::point& Foam::sixDoFRigidBodyMotion::centreOfMass() const { return motionState_.centreOfMass(); diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionIO.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionIO.C similarity index 100% rename from src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionIO.C rename to src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionIO.C diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSpring/linearSpring.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSpring/linearSpring.C new file mode 100644 index 0000000000..b68ce1cf48 --- /dev/null +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSpring/linearSpring.C @@ -0,0 +1,87 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-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 + +\*---------------------------------------------------------------------------*/ + +#include "linearSpring.H" +#include "addToRunTimeSelectionTable.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace sixDoFRigidBodyMotionRestraints +{ + defineTypeNameAndDebug(linearSpring, 0); + addToRunTimeSelectionTable + ( + sixDoFRigidBodyMotionRestraint, + linearSpring, + dictionary + ); +}; +}; + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::sixDoFRigidBodyMotionRestraints::linearSpring::linearSpring +( + const dictionary& sDoFRBMRCoeffs +) +: + sixDoFRigidBodyMotionRestraint(sDoFRBMRCoeffs) +{ + read(sDoFRBMRCoeffs); +} + + +// * * * * * * * * * * * * * * * * Destructors * * * * * * * * * * * * * * * // + +Foam::sixDoFRigidBodyMotionRestraints::linearSpring::~linearSpring() +{} + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +void +Foam::sixDoFRigidBodyMotionRestraints::linearSpring::restraintForce() const +{ + +} + + +bool Foam::sixDoFRigidBodyMotionRestraints::linearSpring::read +( + const dictionary& sDoFRBMRCoeffs +) +{ + sixDoFRigidBodyMotionRestraint::read(sDoFRBMRCoeffs); + + // sDoFRBMRCoeffs_.lookup("velocity") >> velocity_; + + return true; +} + +// ************************************************************************* // diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSpring/linearSpring.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSpring/linearSpring.H new file mode 100644 index 0000000000..dbad5e5cd3 --- /dev/null +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSpring/linearSpring.H @@ -0,0 +1,121 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-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 + Foam::sixDoFRigidBodyMotionRestraints::linearSpring + +Description + sixDoFRigidBodyMotionRestraints model. Linear spring. + +SourceFiles + linearSpring.C + +\*---------------------------------------------------------------------------*/ + +#ifndef linearSpring_H +#define linearSpring_H + +#include "sixDoFRigidBodyMotionRestraint.H" +#include "point.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace sixDoFRigidBodyMotionRestraints +{ + +/*---------------------------------------------------------------------------*\ + Class linearSpring Declaration +\*---------------------------------------------------------------------------*/ + +class linearSpring +: + public sixDoFRigidBodyMotionRestraint +{ + // Private data + + //- Anchor point, where the spring is attached to an immovable + // object + point anchor_; + + //- Reference point of attachment to the solid body + point refAttachmentPt_; + + //- Spring stiffness + scalar stiffness_; + + //- Rest length - length of spring when no forces are applied to it + scalar restLength_; + + +public: + + //- Runtime type information + TypeName("linearSpring"); + + + // Constructors + + //- Construct from components + linearSpring + ( + const dictionary& sDoFRBMRCoeffs + ); + + //- Construct and return a clone + virtual autoPtr clone() const + { + return autoPtr + ( + new linearSpring(*this) + ); + } + + + // Destructor + + virtual ~linearSpring(); + + + // Member Functions + + //- Return the restraint force and point of application + virtual void restraintForce() const; + + //- Update properties from given dictionary + virtual bool read(const dictionary& sDoFRBMRCoeff); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace solidBodyMotionFunctions +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/newSixDoFRigidBodyMotionRestraint.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/newSixDoFRigidBodyMotionRestraint.C new file mode 100644 index 0000000000..1d5484be7a --- /dev/null +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/newSixDoFRigidBodyMotionRestraint.C @@ -0,0 +1,65 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-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 + +\*---------------------------------------------------------------------------*/ + +#include "sixDoFRigidBodyMotionRestraint.H" + +// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * // + +Foam::autoPtr +Foam::sixDoFRigidBodyMotionRestraint::New(const dictionary& sDoFRBMRCoeffs) +{ + word sixDoFRigidBodyMotionRestraintTypeName = + sDoFRBMRCoeffs.lookup("sixDoFRigidBodyMotionRestraint"); + + Info<< "Selecting sixDoFRigidBodyMotionRestraint function " + << sixDoFRigidBodyMotionRestraintTypeName << endl; + + dictionaryConstructorTable::iterator cstrIter = + dictionaryConstructorTablePtr_->find + ( + sixDoFRigidBodyMotionRestraintTypeName + ); + + if (cstrIter == dictionaryConstructorTablePtr_->end()) + { + FatalErrorIn + ( + "sixDoFRigidBodyMotionRestraint::New" + "(" + " const dictionary& sDoFRBMRCoeffs" + ")" + ) << "Unknown sixDoFRigidBodyMotionRestraint type " + << sixDoFRigidBodyMotionRestraintTypeName << endl << endl + << "Valid sixDoFRigidBodyMotionRestraints are : " << endl + << dictionaryConstructorTablePtr_->sortedToc() + << exit(FatalError); + } + + return autoPtr(cstrIter()(sDoFRBMRCoeffs)); +} + + +// ************************************************************************* // diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.C new file mode 100644 index 0000000000..929e8859b1 --- /dev/null +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.C @@ -0,0 +1,72 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-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 + +\*---------------------------------------------------------------------------*/ + +#include "sixDoFRigidBodyMotionRestraint.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +defineTypeNameAndDebug(Foam::sixDoFRigidBodyMotionRestraint, 0); + +defineRunTimeSelectionTable(Foam::sixDoFRigidBodyMotionRestraint, dictionary); + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::sixDoFRigidBodyMotionRestraint::sixDoFRigidBodyMotionRestraint +( + const dictionary& sDoFRBMRCoeffs +) +: + sDoFRBMRCoeffs_ + ( + sDoFRBMRCoeffs.subDict + ( + word(sDoFRBMRCoeffs.lookup("sixDoFRigidBodyMotionRestraint")) + + "Coeffs" + ) + ) +{} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::sixDoFRigidBodyMotionRestraint::~sixDoFRigidBodyMotionRestraint() +{} + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +bool Foam::sixDoFRigidBodyMotionRestraint::read +( + const dictionary& sDoFRBMRCoeffs +) +{ + sDoFRBMRCoeffs_ = sDoFRBMRCoeffs.subDict(type() + "Coeffs"); + + return true; +} + + +// ************************************************************************* // diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.H new file mode 100644 index 0000000000..9d2b2207bd --- /dev/null +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.H @@ -0,0 +1,133 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-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 + +Namespace + Foam::sixDoFRigidBodyMotionRestraints + +Description + Namespace for six DoF motion restraints + + +Class + Foam::sixDoFRigidBodyMotionRestraint + +Description + Base class for defining restraints for sixDoF motions + +SourceFiles + sixDoFRigidBodyMotionRestraint.C + newDynamicFvMesh.C + +\*---------------------------------------------------------------------------*/ + +#ifndef sixDoFRigidBodyMotionRestraint_H +#define sixDoFRigidBodyMotionRestraint_H + +#include "Time.H" +#include "dictionary.H" +#include "autoPtr.H" +#include "runTimeSelectionTables.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class sixDoFRigidBodyMotionRestraint Declaration +\*---------------------------------------------------------------------------*/ + +class sixDoFRigidBodyMotionRestraint +{ + +protected: + + // Protected data + + dictionary sDoFRBMRCoeffs_; + + +public: + + //- Runtime type information + TypeName("sixDoFRigidBodyMotionRestraint"); + + + // Declare run-time constructor selection table + + declareRunTimeSelectionTable + ( + autoPtr, + sixDoFRigidBodyMotionRestraint, + dictionary, + (const dictionary& sDoFRBMRCoeffs), + (sDoFRBMRCoeffs) + ); + + + // Constructors + + //- Construct from the sDoFRBMRCoeffs dictionary and Time + sixDoFRigidBodyMotionRestraint + ( + const dictionary& sDoFRBMRCoeffs + ); + + //- Construct and return a clone + virtual autoPtr clone() const = 0; + + + // Selectors + + //- Select constructed from the sDoFRBMRCoeffs dictionary and Time + static autoPtr New + ( + const dictionary& sDoFRBMRCoeffs + ); + + + // Destructor + + virtual ~sixDoFRigidBodyMotionRestraint(); + + + // Member Functions + + //- Return the restraint force and point of application + virtual void restraintForce() const = 0; + + //- Update properties from given dictionary + virtual bool read(const dictionary& sDoFRBMRCoeffs) = 0; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionState.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionState.C similarity index 100% rename from src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionState.C rename to src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionState.C diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionState.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionState.H similarity index 100% rename from src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionState.H rename to src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionState.H diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionStateI.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionStateI.H similarity index 100% rename from src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionStateI.H rename to src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionStateI.H diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionStateIO.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionStateIO.C similarity index 100% rename from src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionStateIO.C rename to src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionStateIO.C diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/uncoupledSixDoFRigidBodyDisplacement/uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/uncoupledSixDoFRigidBodyDisplacement/uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField.C new file mode 100644 index 0000000000..826dc23f1f --- /dev/null +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/uncoupledSixDoFRigidBodyDisplacement/uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField.C @@ -0,0 +1,163 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-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 + +\*---------------------------------------------------------------------------*/ + +#include "uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField.H" +#include "pointPatchFields.H" +#include "addToRunTimeSelectionTable.H" +#include "Time.H" +#include "fvMesh.H" +#include "volFields.H" +#include "uniformDimensionedFields.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField:: +uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField +( + const pointPatch& p, + const DimensionedField& iF +) +: + fixedValuePointPatchField(p, iF), + motion_(), + p0_(p.localPoints()), + rhoInf_(1.0) +{} + + +uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField:: +uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField +( + const pointPatch& p, + const DimensionedField& iF, + const dictionary& dict +) +: + fixedValuePointPatchField(p, iF, dict), + motion_(dict), + rhoInf_(readScalar(dict.lookup("rhoInf"))) +{ + if (!dict.found("value")) + { + updateCoeffs(); + } + + if (dict.found("p0")) + { + p0_ = vectorField("p0", dict , p.size()); + } + else + { + p0_ = p.localPoints(); + } +} + + +uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField:: +uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField +( + const uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField& ptf, + const pointPatch& p, + const DimensionedField& iF, + const pointPatchFieldMapper& mapper +) +: + fixedValuePointPatchField(ptf, p, iF, mapper), + motion_(ptf.motion_), + p0_(ptf.p0_, mapper), + rhoInf_(ptf.rhoInf_) +{} + + +uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField:: +uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField +( + const uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField& ptf, + const DimensionedField& iF +) +: + fixedValuePointPatchField(ptf, iF), + motion_(ptf.motion_), + p0_(ptf.p0_), + rhoInf_(ptf.rhoInf_) +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField::updateCoeffs() +{ + if (this->updated()) + { + return; + } + + const polyMesh& mesh = this->dimensionedInternalField().mesh()(); + const Time& t = mesh.time(); + + motion_.updatePosition(t.deltaTValue()); + + // Do not modify the accelerations + motion_.updateForce(vector::zero, vector::zero, t.deltaTValue()); + + Field::operator=(motion_.generatePositions(p0_) - p0_); + + fixedValuePointPatchField::updateCoeffs(); +} + + +void uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField::write +( + Ostream& os +) const +{ + pointPatchField::write(os); + motion_.write(os); + os.writeKeyword("rhoInf") + << rhoInf_ << token::END_STATEMENT << nl; + p0_.writeEntry("p0", os); + writeEntry("value", os); +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +makePointPatchTypeField +( + pointPatchVectorField, + uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField +); + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// ************************************************************************* // diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/uncoupledSixDoFRigidBodyDisplacement/uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/uncoupledSixDoFRigidBodyDisplacement/uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField.H new file mode 100644 index 0000000000..fb4177d104 --- /dev/null +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/uncoupledSixDoFRigidBodyDisplacement/uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField.H @@ -0,0 +1,158 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-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 + Foam::uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField + +Description + Foam::uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField + +SourceFiles + uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField.C + +\*---------------------------------------------------------------------------*/ + +#ifndef uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField_H +#define uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField_H + +#include "fixedValuePointPatchField.H" +#include "sixDoFRigidBodyMotion.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField Declaration +\*---------------------------------------------------------------------------*/ + +class uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField +: + public fixedValuePointPatchField +{ + // Private data + + //- Six dof motion object + sixDoFRigidBodyMotion motion_; + + //- Reference positions of points on the patch + pointField p0_; + + //- Reference density required by the forces object for + // incompressible calculations. Retained here to give + // dictionary compatibility with other sixDoF patches. + scalar rhoInf_; + + +public: + + //- Runtime type information + TypeName("uncoupledSixDoFRigidBodyDisplacement"); + + + // Constructors + + //- Construct from patch and internal field + uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField + ( + const pointPatch&, + const DimensionedField& + ); + + //- Construct from patch, internal field and dictionary + uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField + ( + const pointPatch&, + const DimensionedField&, + const dictionary& + ); + + //- Construct by mapping given patchField onto a new patch + uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField + ( + const uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField&, + const pointPatch&, + const DimensionedField&, + const pointPatchFieldMapper& + ); + + //- Construct and return a clone + virtual autoPtr > clone() const + { + return autoPtr > + ( + new uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField + ( + *this + ) + ); + } + + //- Construct as copy setting internal field reference + uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField + ( + const uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField&, + const DimensionedField& + ); + + //- Construct and return a clone setting internal field reference + virtual autoPtr > clone + ( + const DimensionedField& iF + ) const + { + return autoPtr > + ( + new uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField + ( + *this, + iF + ) + ); + } + + + // Member functions + + // Evaluation functions + + //- Update the coefficients associated with the patch field + virtual void updateCoeffs(); + + + //- Write + virtual void write(Ostream&) const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // From 8bcb2c8f11981ac84706eeccd8fa4582389bb2ee Mon Sep 17 00:00:00 2001 From: graham Date: Tue, 26 Jan 2010 15:47:48 +0000 Subject: [PATCH 03/14] sixDoFRigidBody: adding restraints. Applying restraints, which return the force and moment to be applied to the attachment point. Adding linearSpring with along axis damping. Making access functions for the sixDoFRigidBodyMotion data private where possible to prevent erroneous external use of body local data. Fixing bug in unused updateForce(pointField...) function, torques were not being correctly applied. Adding gravity lookup to uncoupledSixDoFRigidBodyDisplacement BC to allow it to be used in, for example, moveDynamicMesh (which would need read gravity into the database). --- ...gidBodyDisplacementPointPatchVectorField.C | 2 +- ...gidBodyDisplacementPointPatchVectorField.C | 2 +- .../sixDoFRigidBodyMotion.C | 31 +++-- .../sixDoFRigidBodyMotion.H | 126 ++++++++++-------- .../sixDoFRigidBodyMotionI.H | 80 +++++++---- .../linearSpring/linearSpring.C | 40 +++++- .../linearSpring/linearSpring.H | 17 ++- .../sixDoFRigidBodyMotionRestraint.H | 16 ++- ...gidBodyDisplacementPointPatchVectorField.C | 16 ++- 9 files changed, 229 insertions(+), 101 deletions(-) diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/constrainedSixDoFRigidBodyDisplacement/constrainedSixDoFRigidBodyDisplacementPointPatchVectorField.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/constrainedSixDoFRigidBodyDisplacement/constrainedSixDoFRigidBodyDisplacementPointPatchVectorField.C index a1516d15a2..01e47944f4 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/constrainedSixDoFRigidBodyDisplacement/constrainedSixDoFRigidBodyDisplacementPointPatchVectorField.C +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/constrainedSixDoFRigidBodyDisplacement/constrainedSixDoFRigidBodyDisplacementPointPatchVectorField.C @@ -171,7 +171,7 @@ void constrainedSixDoFRigidBodyDisplacementPointPatchVectorField::updateCoeffs() t.deltaTValue() ); - Field::operator=(motion_.generatePositions(p0_) - p0_); + Field::operator=(motion_.currentPosition(p0_) - p0_); fixedValuePointPatchField::updateCoeffs(); } diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyDisplacementPointPatchVectorField.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyDisplacementPointPatchVectorField.C index 660ccb056b..dce0389466 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyDisplacementPointPatchVectorField.C +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyDisplacementPointPatchVectorField.C @@ -180,7 +180,7 @@ void sixDoFRigidBodyDisplacementPointPatchVectorField::updateCoeffs() // ); // ---------------------------------------- - Field::operator=(motion_.generatePositions(p0_) - p0_); + Field::operator=(motion_.currentPosition(p0_) - p0_); fixedValuePointPatchField::updateCoeffs(); } diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C index 39dafe9a06..d892836425 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C @@ -30,9 +30,27 @@ License void Foam::sixDoFRigidBodyMotion::applyRestraints() { - forAll(restraints_, rI) + if (Pstream::master()) { - restraints_[rI].restraintForce(); + forAll(restraints_, rI) + { + // restraint position + point rP = vector::zero; + + // restraint force + vector rF = vector::zero; + + // restraint moment + vector rM = vector::zero; + + restraints_[rI].restrain(*this, rP, rF, rM); + + Info<< "Restraint " << rI << " force " << rF << endl; + + a() += rF/mass_; + + tau() += Q().T() & (rM + (rP - centreOfMass()) ^ rF); + } } } @@ -202,7 +220,6 @@ void Foam::sixDoFRigidBodyMotion::updatePosition R = rotationTensorX(0.5*deltaT*pi().x()/momentOfInertia_.xx()); pi() = pi() & R; Q() = Q() & R; - } Pstream::scatter(motionState_); @@ -257,7 +274,7 @@ void Foam::sixDoFRigidBodyMotion::updateForce a += f/mass_; - tau += (positions[i] ^ (Q().T() & f)); + tau += Q().T() & ((positions[i] - centreOfMass()) ^ f); } } @@ -265,11 +282,5 @@ void Foam::sixDoFRigidBodyMotion::updateForce } -Foam::tmp -Foam::sixDoFRigidBodyMotion::generatePositions(const pointField& pts) const -{ - return (centreOfMass() + (Q() & (pts - refCentreOfMass_))); -} - // ************************************************************************* // diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.H index 2a4efa52bb..274b62be76 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.H +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.H @@ -123,6 +123,63 @@ class sixDoFRigidBodyMotion //- Apply the constraints to the object void applyConstraints(); + // Access functions retained as private because of the risk of + // confusion over what is a body local frame vector and what is global + + // Access + + //- Return access to the motion state + inline const sixDoFRigidBodyMotionState& motionState() const; + + //- Return access to the restraints + inline const PtrList& + restraints() const; + + //- Return access to the centre of mass + inline const point& refCentreOfMass() const; + + //- Return access to the inertia tensor + inline const diagTensor& momentOfInertia() const; + + //- Return access to the orientation + inline const tensor& Q() const; + + //- Return access to velocity + inline const vector& v() const; + + //- Return access to acceleration + inline const vector& a() const; + + //- Return access to angular momentum + inline const vector& pi() const; + + //- Return access to torque + inline const vector& tau() const; + + + // Edit + + //- Return access to the centre of mass + inline point& refCentreOfMass(); + + //- Return non-const access to the inertia tensor + inline diagTensor& momentOfInertia(); + + //- Return non-const access to the orientation + inline tensor& Q(); + + //- Return non-const access to vector + inline vector& v(); + + //- Return non-const access to acceleration + inline vector& a(); + + //- Return non-const access to angular momentum + inline vector& pi(); + + //- Return non-const access to torque + inline vector& tau(); + public: @@ -191,75 +248,38 @@ public: scalar deltaT ); - //- Transform the given pointField by the current motion state - tmp generatePositions(const pointField& pts) const; + //- Transform the given reference state pointField by the + // current motion state + inline tmp currentPosition(const pointField& pts) const; + + //- Transform the given reference state point by the current + // motion state + inline point currentPosition(const point& pt) const; + + //- Return the angular velocity in the global frame + inline vector omega() const; + + //- Return the velocity of a position given by the current + // motion state + inline point currentVelocity(const point& pt) const; // Access - //- Return access to the motion state - inline const sixDoFRigidBodyMotionState& motionState() const; - - //- Return access to the restraints - inline const PtrList& - restraints() const; - - //- Return access to the centre of mass + //- Return const access to the centre of mass inline const point& centreOfMass() const; - //- Return access to the centre of mass - inline const point& refCentreOfMass() const; - - //- Return access to the inertia tensor - inline const diagTensor& momentOfInertia() const; - - //- Return access to the mass + //- Return const access to the mass inline scalar mass() const; - //- Return access to the orientation - inline const tensor& Q() const; - - //- Return access to velocity - inline const vector& v() const; - - //- Return access to acceleration - inline const vector& a() const; - - //- Return access to angular momentum - inline const vector& pi() const; - - //- Return access to torque - inline const vector& tau() const; - // Edit //- Return non-const access to the centre of mass inline point& centreOfMass(); - //- Return access to the centre of mass - inline point& refCentreOfMass(); - - //- Return non-const access to the inertia tensor - inline diagTensor& momentOfInertia(); - //- Return non-const access to the mass inline scalar& mass(); - //- Return non-const access to the orientation - inline tensor& Q(); - - //- Return non-const access to vector - inline vector& v(); - - //- Return non-const access to acceleration - inline vector& a(); - - //- Return non-const access to angular momentum - inline vector& pi(); - - //- Return non-const access to torque - inline vector& tau(); - //- Write void write(Ostream&) const; diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionI.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionI.H index 835dbe5c8a..ae80cb18a3 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionI.H +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionI.H @@ -76,12 +76,6 @@ Foam::sixDoFRigidBodyMotion::restraints() const } -inline const Foam::point& Foam::sixDoFRigidBodyMotion::centreOfMass() const -{ - return motionState_.centreOfMass(); -} - - inline const Foam::point& Foam::sixDoFRigidBodyMotion::refCentreOfMass() const { return refCentreOfMass_; @@ -95,12 +89,6 @@ Foam::sixDoFRigidBodyMotion::momentOfInertia() const } -inline Foam::scalar Foam::sixDoFRigidBodyMotion::mass() const -{ - return mass_; -} - - inline const Foam::tensor& Foam::sixDoFRigidBodyMotion::Q() const { return motionState_.Q(); @@ -131,12 +119,6 @@ inline const Foam::vector& Foam::sixDoFRigidBodyMotion::tau() const } -inline Foam::point& Foam::sixDoFRigidBodyMotion::centreOfMass() -{ - return motionState_.centreOfMass(); -} - - inline Foam::point& Foam::sixDoFRigidBodyMotion::refCentreOfMass() { return refCentreOfMass_; @@ -149,12 +131,6 @@ inline Foam::diagTensor& Foam::sixDoFRigidBodyMotion::momentOfInertia() } -inline Foam::scalar& Foam::sixDoFRigidBodyMotion::mass() -{ - return mass_; -} - - inline Foam::tensor& Foam::sixDoFRigidBodyMotion::Q() { return motionState_.Q(); @@ -185,4 +161,60 @@ inline Foam::vector& Foam::sixDoFRigidBodyMotion::tau() } +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +inline Foam::tmp +Foam::sixDoFRigidBodyMotion::currentPosition(const pointField& pts) const +{ + return (centreOfMass() + (Q() & (pts - refCentreOfMass_))); +} + + +inline Foam::point Foam::sixDoFRigidBodyMotion::currentPosition +( + const point& pt +) const +{ + return (centreOfMass() + (Q() & (pt - refCentreOfMass_))); +} + + +inline Foam::vector Foam::sixDoFRigidBodyMotion::omega() const +{ + return Q() & (inv(momentOfInertia_) & pi()); +} + + +inline Foam::point Foam::sixDoFRigidBodyMotion::currentVelocity +( + const point& pt +) const +{ + return (omega() ^ (pt - centreOfMass())) + v(); +} + + +inline const Foam::point& Foam::sixDoFRigidBodyMotion::centreOfMass() const +{ + return motionState_.centreOfMass(); +} + + +inline Foam::scalar Foam::sixDoFRigidBodyMotion::mass() const +{ + return mass_; +} + + +inline Foam::point& Foam::sixDoFRigidBodyMotion::centreOfMass() +{ + return motionState_.centreOfMass(); +} + + +inline Foam::scalar& Foam::sixDoFRigidBodyMotion::mass() +{ + return mass_; +} + // ************************************************************************* // diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSpring/linearSpring.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSpring/linearSpring.C index b68ce1cf48..79c66836e9 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSpring/linearSpring.C +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSpring/linearSpring.C @@ -26,6 +26,7 @@ License #include "linearSpring.H" #include "addToRunTimeSelectionTable.H" +#include "sixDoFRigidBodyMotion.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // @@ -51,7 +52,12 @@ Foam::sixDoFRigidBodyMotionRestraints::linearSpring::linearSpring const dictionary& sDoFRBMRCoeffs ) : - sixDoFRigidBodyMotionRestraint(sDoFRBMRCoeffs) + sixDoFRigidBodyMotionRestraint(sDoFRBMRCoeffs), + anchor_(), + refAttachmentPt_(), + stiffness_(), + damping_(), + restLength_() { read(sDoFRBMRCoeffs); } @@ -65,10 +71,28 @@ Foam::sixDoFRigidBodyMotionRestraints::linearSpring::~linearSpring() // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // -void -Foam::sixDoFRigidBodyMotionRestraints::linearSpring::restraintForce() const +void Foam::sixDoFRigidBodyMotionRestraints::linearSpring::restrain +( + const sixDoFRigidBodyMotion& motion, + vector& restraintPosition, + vector& restraintForce, + vector& restraintMoment +) const { + restraintPosition = motion.currentPosition(refAttachmentPt_); + vector r = restraintPosition - anchor_; + + scalar magR = mag(r); + + // r is now the r unit vector + r /= magR; + + vector v = motion.currentVelocity(restraintPosition); + + restraintForce = -stiffness_*(magR - restLength_)*r - damping_*(r & v)*r; + + restraintMoment = vector::zero; } @@ -79,7 +103,15 @@ bool Foam::sixDoFRigidBodyMotionRestraints::linearSpring::read { sixDoFRigidBodyMotionRestraint::read(sDoFRBMRCoeffs); - // sDoFRBMRCoeffs_.lookup("velocity") >> velocity_; + sDoFRBMRCoeffs_.lookup("anchor") >> anchor_; + + sDoFRBMRCoeffs_.lookup("refAttachmentPt") >> refAttachmentPt_; + + sDoFRBMRCoeffs_.lookup("stiffness") >> stiffness_; + + sDoFRBMRCoeffs_.lookup("damping") >> damping_; + + sDoFRBMRCoeffs_.lookup("restLength") >> restLength_; return true; } diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSpring/linearSpring.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSpring/linearSpring.H index dbad5e5cd3..34a83a1ce8 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSpring/linearSpring.H +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSpring/linearSpring.H @@ -43,6 +43,7 @@ SourceFiles namespace Foam { + namespace sixDoFRigidBodyMotionRestraints { @@ -63,9 +64,12 @@ class linearSpring //- Reference point of attachment to the solid body point refAttachmentPt_; - //- Spring stiffness + //- Spring stiffness coefficient (N/m) scalar stiffness_; + //- Damping coefficient (Ns/m) + scalar damping_; + //- Rest length - length of spring when no forces are applied to it scalar restLength_; @@ -101,8 +105,15 @@ public: // Member Functions - //- Return the restraint force and point of application - virtual void restraintForce() const; + //- Calculate the restraint position, force and moment. + // Global reference frame vectors. + virtual void restrain + ( + const sixDoFRigidBodyMotion& motion, + vector& restraintPosition, + vector& restraintForce, + vector& restraintMoment + ) const; //- Update properties from given dictionary virtual bool read(const dictionary& sDoFRBMRCoeff); diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.H index 9d2b2207bd..65c0c0d6d3 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.H +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.H @@ -47,6 +47,7 @@ SourceFiles #include "Time.H" #include "dictionary.H" #include "autoPtr.H" +#include "vector.H" #include "runTimeSelectionTables.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -54,6 +55,10 @@ SourceFiles namespace Foam { +// Forward declaration of classes +class sixDoFRigidBodyMotion; + + /*---------------------------------------------------------------------------*\ Class sixDoFRigidBodyMotionRestraint Declaration \*---------------------------------------------------------------------------*/ @@ -114,8 +119,15 @@ public: // Member Functions - //- Return the restraint force and point of application - virtual void restraintForce() const = 0; + //- Calculate the restraint position, force and moment. + // Global reference frame vectors. + virtual void restrain + ( + const sixDoFRigidBodyMotion& motion, + vector& restraintPosition, + vector& restraintForce, + vector& restraintMoment + ) const = 0; //- Update properties from given dictionary virtual bool read(const dictionary& sDoFRBMRCoeffs) = 0; diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/uncoupledSixDoFRigidBodyDisplacement/uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/uncoupledSixDoFRigidBodyDisplacement/uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField.C index 826dc23f1f..d35eefd671 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/uncoupledSixDoFRigidBodyDisplacement/uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField.C +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/uncoupledSixDoFRigidBodyDisplacement/uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField.C @@ -125,10 +125,20 @@ void uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField::updateCoeffs() motion_.updatePosition(t.deltaTValue()); - // Do not modify the accelerations - motion_.updateForce(vector::zero, vector::zero, t.deltaTValue()); + vector gravity = vector::zero; - Field::operator=(motion_.generatePositions(p0_) - p0_); + if (db().foundObject("g")) + { + uniformDimensionedVectorField g = + db().lookupObject("g"); + + gravity = g.value(); + } + + // Do not modify the accelerations, except with gravity, where available + motion_.updateForce(gravity*motion_.mass(), vector::zero, t.deltaTValue()); + + Field::operator=(motion_.currentPosition(p0_) - p0_); fixedValuePointPatchField::updateCoeffs(); } From a0522a2b7bfe12a3aab0d586f7d646ca1d4cc906 Mon Sep 17 00:00:00 2001 From: graham Date: Tue, 26 Jan 2010 17:51:38 +0000 Subject: [PATCH 04/14] sixDoFRigidBody: adding constraints. Adding outline and placeholders for constraints and their solution. --- .../functionObjects/forces/Make/files | 6 + .../sixDoFRigidBodyMotion.C | 93 ++++++++++- .../sixDoFRigidBodyMotion.H | 22 ++- .../fixedPoint/fixedPoint.C | 109 +++++++++++++ .../fixedPoint/fixedPoint.H | 124 ++++++++++++++ .../newSixDoFRigidBodyMotionConstraint.C | 65 ++++++++ .../sixDoFRigidBodyMotionConstraint.C | 75 +++++++++ .../sixDoFRigidBodyMotionConstraint.H | 154 ++++++++++++++++++ .../sixDoFRigidBodyMotionI.H | 7 + .../linearSpring/linearSpring.C | 10 +- .../linearSpring/linearSpring.H | 2 +- .../newSixDoFRigidBodyMotionRestraint.C | 8 +- .../sixDoFRigidBodyMotionRestraint.C | 10 +- .../sixDoFRigidBodyMotionRestraint.H | 14 +- 14 files changed, 671 insertions(+), 28 deletions(-) create mode 100644 src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPoint/fixedPoint.C create mode 100644 src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPoint/fixedPoint.H create mode 100644 src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint/newSixDoFRigidBodyMotionConstraint.C create mode 100644 src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint.C create mode 100644 src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint.H diff --git a/src/postProcessing/functionObjects/forces/Make/files b/src/postProcessing/functionObjects/forces/Make/files index 66f3c0a8ec..a7541d14c0 100644 --- a/src/postProcessing/functionObjects/forces/Make/files +++ b/src/postProcessing/functionObjects/forces/Make/files @@ -17,6 +17,12 @@ $(sDoFRBMR)/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.C $(sDoFRBMR)/sixDoFRigidBodyMotionRestraint/newSixDoFRigidBodyMotionRestraint.C $(sDoFRBMR)/linearSpring/linearSpring.C +sDoFRBMC = $(sDoFRBM)/sixDoFRigidBodyMotionConstraint + +$(sDoFRBMC)/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint.C +$(sDoFRBMC)/sixDoFRigidBodyMotionConstraint/newSixDoFRigidBodyMotionConstraint.C +$(sDoFRBMC)/fixedPoint/fixedPoint.C + pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyDisplacementPointPatchVectorField.C pointPatchFields/derived/uncoupledSixDoFRigidBodyDisplacement/uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField.C pointPatchFields/derived/constrainedSixDoFRigidBodyDisplacement/constrainedSixDoFRigidBodyDisplacementPointPatchVectorField.C diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C index d892836425..0eef0872e8 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C @@ -49,15 +49,61 @@ void Foam::sixDoFRigidBodyMotion::applyRestraints() a() += rF/mass_; - tau() += Q().T() & (rM + (rP - centreOfMass()) ^ rF); + tau() += Q().T() & (rM + ((rP - centreOfMass()) ^ rF)); } } } -void Foam::sixDoFRigidBodyMotion::applyConstraints() +void Foam::sixDoFRigidBodyMotion::applyConstraints(scalar deltaT) { + if (Pstream::master()) + { + label iter = 0; + bool converged = true; + + // constraint force accumulator + vector cFA = vector::zero; + + // constraint moment accumulator + vector cMA = vector::zero; + + do + { + converged = true; + + Info<< "Iteration " << iter << endl; + + forAll(constraints_, cI) + { + Info<< "Constraint " << cI << endl; + + // constraint position + point cP = vector::zero; + + // constraint force + vector cF = vector::zero; + + // constraint moment + vector cM = vector::zero; + + converged = converged && constraints_[cI].constrain + ( + *this, + cFA, + cMA, + deltaT, + cP, + cF, + cM + ); + } + + iter++; + + } while(!converged); + } } @@ -67,6 +113,7 @@ Foam::sixDoFRigidBodyMotion::sixDoFRigidBodyMotion() : motionState_(), restraints_(), + constraints_(), refCentreOfMass_(vector::zero), momentOfInertia_(diagTensor::one*VSMALL), mass_(VSMALL) @@ -96,6 +143,7 @@ Foam::sixDoFRigidBodyMotion::sixDoFRigidBodyMotion tau ), restraints_(), + constraints_(), refCentreOfMass_(refCentreOfMass), momentOfInertia_(momentOfInertia), mass_(mass) @@ -106,6 +154,7 @@ Foam::sixDoFRigidBodyMotion::sixDoFRigidBodyMotion(const dictionary& dict) : motionState_(dict), restraints_(), + constraints_(), refCentreOfMass_(dict.lookupOrDefault("refCentreOfMass", centreOfMass())), momentOfInertia_(dict.lookup("momentOfInertia")), mass_(readScalar(dict.lookup("mass"))) @@ -123,6 +172,7 @@ Foam::sixDoFRigidBodyMotion::sixDoFRigidBodyMotion : motionState_(sDoFRBM.motionState()), restraints_(sDoFRBM.restraints()), + constraints_(sDoFRBM.constraints()), refCentreOfMass_(sDoFRBM.refCentreOfMass()), momentOfInertia_(sDoFRBM.momentOfInertia()), mass_(sDoFRBM.mass()) @@ -176,7 +226,32 @@ void Foam::sixDoFRigidBodyMotion::addConstraints const dictionary& dict ) { + if (dict.found("constraints")) + { + const dictionary& constraintDict = dict.subDict("constraints"); + label i = 0; + + constraints_.setSize(constraintDict.size()); + + forAllConstIter(IDLList, constraintDict, iter) + { + if (iter().isDict()) + { + Info<< "Adding constraint: " << iter().keyword() << endl; + + constraints_.set + ( + i, + sixDoFRigidBodyMotionConstraint::New(iter().dict()) + ); + } + + i++; + } + + constraints_.setSize(i); + } } @@ -244,7 +319,7 @@ void Foam::sixDoFRigidBodyMotion::updateForce applyRestraints(); - applyConstraints(); + applyConstraints(deltaT); v() += 0.5*deltaT*a(); @@ -282,5 +357,17 @@ void Foam::sixDoFRigidBodyMotion::updateForce } +Foam::point Foam::sixDoFRigidBodyMotion::predictedPosition +( + const point& pt, + const vector deltaForce, + const vector deltaMoment, + scalar deltaT +) const +{ + Info<< "predictedPosition NOT IMPLEMENTED" << endl; + return pt; +} + // ************************************************************************* // diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.H index 274b62be76..4b1c724414 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.H +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.H @@ -59,6 +59,7 @@ SourceFiles #include "sixDoFRigidBodyMotionState.H" #include "pointField.H" #include "sixDoFRigidBodyMotionRestraint.H" +#include "sixDoFRigidBodyMotionConstraint.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -90,8 +91,8 @@ class sixDoFRigidBodyMotion //- Restraints on the motion PtrList restraints_; - // //- Constaints on the motion - // PtrList constraints_; + //- Constaints on the motion + PtrList constraints_; //- Centre of mass of reference state point refCentreOfMass_; @@ -121,7 +122,7 @@ class sixDoFRigidBodyMotion void applyRestraints(); //- Apply the constraints to the object - void applyConstraints(); + void applyConstraints(scalar deltaT); // Access functions retained as private because of the risk of // confusion over what is a body local frame vector and what is global @@ -135,6 +136,10 @@ class sixDoFRigidBodyMotion inline const PtrList& restraints() const; + //- Return access to the constraints + inline const PtrList& + constraints() const; + //- Return access to the centre of mass inline const point& refCentreOfMass() const; @@ -256,6 +261,17 @@ public: // motion state inline point currentPosition(const point& pt) const; + //- Predict the position of the supplied point after deltaT + // given the current motion state and the additional supplied + // force and moment + point predictedPosition + ( + const point& pt, + const vector deltaForce, + const vector deltaMoment, + scalar deltaT + ) const; + //- Return the angular velocity in the global frame inline vector omega() const; diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPoint/fixedPoint.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPoint/fixedPoint.C new file mode 100644 index 0000000000..7ff526fe07 --- /dev/null +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPoint/fixedPoint.C @@ -0,0 +1,109 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-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 + +\*---------------------------------------------------------------------------*/ + +#include "fixedPoint.H" +#include "addToRunTimeSelectionTable.H" +#include "sixDoFRigidBodyMotion.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace sixDoFRigidBodyMotionConstraints +{ + defineTypeNameAndDebug(fixedPoint, 0); + addToRunTimeSelectionTable + ( + sixDoFRigidBodyMotionConstraint, + fixedPoint, + dictionary + ); +}; +}; + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::sixDoFRigidBodyMotionConstraints::fixedPoint::fixedPoint +( + const dictionary& sDoFRBMCDict +) +: + sixDoFRigidBodyMotionConstraint(sDoFRBMCDict), + fixedPoint_() +{ + read(sDoFRBMCDict); +} + + +// * * * * * * * * * * * * * * * * Destructors * * * * * * * * * * * * * * * // + +Foam::sixDoFRigidBodyMotionConstraints::fixedPoint::~fixedPoint() +{} + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +bool Foam::sixDoFRigidBodyMotionConstraints::fixedPoint::constrain +( + const sixDoFRigidBodyMotion& motion, + const vector& existingConstraintForce, + const vector& existingConstraintMoment, + scalar deltaT, + vector& constraintPosition, + vector& constraintForceIncrement, + vector& constraintMomentIncrement +) const +{ + point predictedPosition = motion.predictedPosition + ( + fixedPoint_, + existingConstraintForce, + existingConstraintMoment, + deltaT + ); + + vector error = predictedPosition - fixedPoint_; + + Info<< error << endl; + + return true; +} + + +bool Foam::sixDoFRigidBodyMotionConstraints::fixedPoint::read +( + const dictionary& sDoFRBMCDict +) +{ + sixDoFRigidBodyMotionConstraint::read(sDoFRBMCDict); + + sDoFRBMCCoeffs_.lookup("fixedPoint") >> fixedPoint_; + + return true; +} + +// ************************************************************************* // diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPoint/fixedPoint.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPoint/fixedPoint.H new file mode 100644 index 0000000000..9619d8e72f --- /dev/null +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPoint/fixedPoint.H @@ -0,0 +1,124 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-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 + Foam::sixDoFRigidBodyMotionConstraints::fixedPoint + +Description + sixDoFRigidBodyMotionConstraint. Point fixed in space. + +SourceFiles + fixedPoint.C + +\*---------------------------------------------------------------------------*/ + +#ifndef fixedPoint_H +#define fixedPoint_H + +#include "sixDoFRigidBodyMotionConstraint.H" +#include "point.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +namespace sixDoFRigidBodyMotionConstraints +{ + +/*---------------------------------------------------------------------------*\ + Class fixedPoint Declaration +\*---------------------------------------------------------------------------*/ + +class fixedPoint +: + public sixDoFRigidBodyMotionConstraint +{ + // Private data + + //- Point which is rigidly attached to the body and constrains + // it so that this point remains fixed. + point fixedPoint_; + + +public: + + //- Runtime type information + TypeName("fixedPoint"); + + + // Constructors + + //- Construct from components + fixedPoint + ( + const dictionary& sDoFRBMCDict + ); + + //- Construct and return a clone + virtual autoPtr clone() const + { + return autoPtr + ( + new fixedPoint(*this) + ); + } + + + // Destructor + + virtual ~fixedPoint(); + + + // Member Functions + + //- Calculate the constraint position, force and moment. + // Global reference frame vectors. Returns boolean stating + // whether the constraint been converged to tolerance. + virtual bool constrain + ( + const sixDoFRigidBodyMotion& motion, + const vector& existingConstraintForce, + const vector& existingConstraintMoment, + scalar deltaT, + vector& constraintPosition, + vector& constraintForceIncrement, + vector& constraintMomentIncrement + ) const; + + //- Update properties from given dictionary + virtual bool read(const dictionary& sDoFRBMCCoeff); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace solidBodyMotionFunctions +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint/newSixDoFRigidBodyMotionConstraint.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint/newSixDoFRigidBodyMotionConstraint.C new file mode 100644 index 0000000000..890a83b2c0 --- /dev/null +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint/newSixDoFRigidBodyMotionConstraint.C @@ -0,0 +1,65 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-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 + +\*---------------------------------------------------------------------------*/ + +#include "sixDoFRigidBodyMotionConstraint.H" + +// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * // + +Foam::autoPtr +Foam::sixDoFRigidBodyMotionConstraint::New(const dictionary& sDoFRBMCDict) +{ + word sixDoFRigidBodyMotionConstraintTypeName = + sDoFRBMCDict.lookup("sixDoFRigidBodyMotionConstraint"); + + Info<< "Selecting sixDoFRigidBodyMotionConstraint function " + << sixDoFRigidBodyMotionConstraintTypeName << endl; + + dictionaryConstructorTable::iterator cstrIter = + dictionaryConstructorTablePtr_->find + ( + sixDoFRigidBodyMotionConstraintTypeName + ); + + if (cstrIter == dictionaryConstructorTablePtr_->end()) + { + FatalErrorIn + ( + "sixDoFRigidBodyMotionConstraint::New" + "(" + "const dictionary& sDoFRBMCDict" + ")" + ) << "Unknown sixDoFRigidBodyMotionConstraint type " + << sixDoFRigidBodyMotionConstraintTypeName << endl << endl + << "Valid sixDoFRigidBodyMotionConstraints are : " << endl + << dictionaryConstructorTablePtr_->sortedToc() + << exit(FatalError); + } + + return autoPtr(cstrIter()(sDoFRBMCDict)); +} + + +// ************************************************************************* // diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint.C new file mode 100644 index 0000000000..bb8c50b3a5 --- /dev/null +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint.C @@ -0,0 +1,75 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-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 + +\*---------------------------------------------------------------------------*/ + +#include "sixDoFRigidBodyMotionConstraint.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +defineTypeNameAndDebug(Foam::sixDoFRigidBodyMotionConstraint, 0); + +defineRunTimeSelectionTable(Foam::sixDoFRigidBodyMotionConstraint, dictionary); + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::sixDoFRigidBodyMotionConstraint::sixDoFRigidBodyMotionConstraint +( + const dictionary& sDoFRBMCDict +) +: + sDoFRBMCCoeffs_ + ( + sDoFRBMCDict.subDict + ( + word(sDoFRBMCDict.lookup("sixDoFRigidBodyMotionConstraint")) + + "Coeffs" + ) + ), + tolerance_(readScalar(sDoFRBMCDict.lookup("tolerance"))) +{} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::sixDoFRigidBodyMotionConstraint::~sixDoFRigidBodyMotionConstraint() +{} + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +bool Foam::sixDoFRigidBodyMotionConstraint::read +( + const dictionary& sDoFRBMCDict +) +{ + tolerance_ = (readScalar(sDoFRBMCDict.lookup("tolerance"))); + + sDoFRBMCCoeffs_ = sDoFRBMCDict.subDict(type() + "Coeffs"); + + return true; +} + + +// ************************************************************************* // diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint.H new file mode 100644 index 0000000000..be240dce2b --- /dev/null +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint.H @@ -0,0 +1,154 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-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 + +Namespace + Foam::sixDoFRigidBodyMotionConstraints + +Description + Namespace for six DoF motion constraints + + +Class + Foam::sixDoFRigidBodyMotionConstraint + +Description + Base class for defining constraints for sixDoF motions + +SourceFiles + sixDoFRigidBodyMotionConstraint.C + newDynamicFvMesh.C + +\*---------------------------------------------------------------------------*/ + +#ifndef sixDoFRigidBodyMotionConstraint_H +#define sixDoFRigidBodyMotionConstraint_H + +#include "Time.H" +#include "dictionary.H" +#include "autoPtr.H" +#include "vector.H" +#include "runTimeSelectionTables.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward declaration of classes +class sixDoFRigidBodyMotion; + + +/*---------------------------------------------------------------------------*\ + Class sixDoFRigidBodyMotionConstraint Declaration +\*---------------------------------------------------------------------------*/ + +class sixDoFRigidBodyMotionConstraint +{ + +protected: + + // Protected data + + //- Constraint model specific coefficient dictionary + dictionary sDoFRBMCCoeffs_; + + //- Solution tolerance. Meaning depends on model, usually an + // absolute distance or angle. + scalar tolerance_; + + +public: + + //- Runtime type information + TypeName("sixDoFRigidBodyMotionConstraint"); + + + // Declare run-time constructor selection table + + declareRunTimeSelectionTable + ( + autoPtr, + sixDoFRigidBodyMotionConstraint, + dictionary, + (const dictionary& sDoFRBMCDict), + (sDoFRBMCDict) + ); + + + // Constructors + + //- Construct from the sDoFRBMCDict dictionary and Time + sixDoFRigidBodyMotionConstraint + ( + const dictionary& sDoFRBMCDict + ); + + //- Construct and return a clone + virtual autoPtr clone() const = 0; + + + // Selectors + + //- Select constructed from the sDoFRBMCDict dictionary and Time + static autoPtr New + ( + const dictionary& sDoFRBMCDict + ); + + + // Destructor + + virtual ~sixDoFRigidBodyMotionConstraint(); + + + // Member Functions + + //- Calculate the constraint position, force and moment. + // Global reference frame vectors. Returns boolean stating + // whether the constraint been converged to tolerance. + virtual bool constrain + ( + const sixDoFRigidBodyMotion& motion, + const vector& existingConstraintForce, + const vector& existingConstraintMoment, + scalar deltaT, + vector& constraintPosition, + vector& constraintForceIncrement, + vector& constraintMomentIncrement + ) const = 0; + + //- Update properties from given dictionary + virtual bool read(const dictionary& sDoFRBMCDict) = 0; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionI.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionI.H index ae80cb18a3..5b0d607ef4 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionI.H +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionI.H @@ -76,6 +76,13 @@ Foam::sixDoFRigidBodyMotion::restraints() const } +inline const Foam::PtrList& +Foam::sixDoFRigidBodyMotion::constraints() const +{ + return constraints_; +} + + inline const Foam::point& Foam::sixDoFRigidBodyMotion::refCentreOfMass() const { return refCentreOfMass_; diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSpring/linearSpring.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSpring/linearSpring.C index 79c66836e9..966e911c6e 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSpring/linearSpring.C +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSpring/linearSpring.C @@ -49,17 +49,17 @@ namespace sixDoFRigidBodyMotionRestraints Foam::sixDoFRigidBodyMotionRestraints::linearSpring::linearSpring ( - const dictionary& sDoFRBMRCoeffs + const dictionary& sDoFRBMRDict ) : - sixDoFRigidBodyMotionRestraint(sDoFRBMRCoeffs), + sixDoFRigidBodyMotionRestraint(sDoFRBMRDict), anchor_(), refAttachmentPt_(), stiffness_(), damping_(), restLength_() { - read(sDoFRBMRCoeffs); + read(sDoFRBMRDict); } @@ -98,10 +98,10 @@ void Foam::sixDoFRigidBodyMotionRestraints::linearSpring::restrain bool Foam::sixDoFRigidBodyMotionRestraints::linearSpring::read ( - const dictionary& sDoFRBMRCoeffs + const dictionary& sDoFRBMRDict ) { - sixDoFRigidBodyMotionRestraint::read(sDoFRBMRCoeffs); + sixDoFRigidBodyMotionRestraint::read(sDoFRBMRDict); sDoFRBMRCoeffs_.lookup("anchor") >> anchor_; diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSpring/linearSpring.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSpring/linearSpring.H index 34a83a1ce8..c5dc9bc074 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSpring/linearSpring.H +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSpring/linearSpring.H @@ -85,7 +85,7 @@ public: //- Construct from components linearSpring ( - const dictionary& sDoFRBMRCoeffs + const dictionary& sDoFRBMRDict ); //- Construct and return a clone diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/newSixDoFRigidBodyMotionRestraint.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/newSixDoFRigidBodyMotionRestraint.C index 1d5484be7a..7fee5eb84e 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/newSixDoFRigidBodyMotionRestraint.C +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/newSixDoFRigidBodyMotionRestraint.C @@ -29,10 +29,10 @@ License // * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * // Foam::autoPtr -Foam::sixDoFRigidBodyMotionRestraint::New(const dictionary& sDoFRBMRCoeffs) +Foam::sixDoFRigidBodyMotionRestraint::New(const dictionary& sDoFRBMRDict) { word sixDoFRigidBodyMotionRestraintTypeName = - sDoFRBMRCoeffs.lookup("sixDoFRigidBodyMotionRestraint"); + sDoFRBMRDict.lookup("sixDoFRigidBodyMotionRestraint"); Info<< "Selecting sixDoFRigidBodyMotionRestraint function " << sixDoFRigidBodyMotionRestraintTypeName << endl; @@ -49,7 +49,7 @@ Foam::sixDoFRigidBodyMotionRestraint::New(const dictionary& sDoFRBMRCoeffs) ( "sixDoFRigidBodyMotionRestraint::New" "(" - " const dictionary& sDoFRBMRCoeffs" + "const dictionary& sDoFRBMRDict" ")" ) << "Unknown sixDoFRigidBodyMotionRestraint type " << sixDoFRigidBodyMotionRestraintTypeName << endl << endl @@ -58,7 +58,7 @@ Foam::sixDoFRigidBodyMotionRestraint::New(const dictionary& sDoFRBMRCoeffs) << exit(FatalError); } - return autoPtr(cstrIter()(sDoFRBMRCoeffs)); + return autoPtr(cstrIter()(sDoFRBMRDict)); } diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.C index 929e8859b1..2d17503421 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.C +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.C @@ -36,14 +36,14 @@ defineRunTimeSelectionTable(Foam::sixDoFRigidBodyMotionRestraint, dictionary); Foam::sixDoFRigidBodyMotionRestraint::sixDoFRigidBodyMotionRestraint ( - const dictionary& sDoFRBMRCoeffs + const dictionary& sDoFRBMRDict ) : sDoFRBMRCoeffs_ ( - sDoFRBMRCoeffs.subDict + sDoFRBMRDict.subDict ( - word(sDoFRBMRCoeffs.lookup("sixDoFRigidBodyMotionRestraint")) + word(sDoFRBMRDict.lookup("sixDoFRigidBodyMotionRestraint")) + "Coeffs" ) ) @@ -60,10 +60,10 @@ Foam::sixDoFRigidBodyMotionRestraint::~sixDoFRigidBodyMotionRestraint() bool Foam::sixDoFRigidBodyMotionRestraint::read ( - const dictionary& sDoFRBMRCoeffs + const dictionary& sDoFRBMRDict ) { - sDoFRBMRCoeffs_ = sDoFRBMRCoeffs.subDict(type() + "Coeffs"); + sDoFRBMRCoeffs_ = sDoFRBMRDict.subDict(type() + "Coeffs"); return true; } diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.H index 65c0c0d6d3..b9e0d5f0f1 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.H +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.H @@ -86,17 +86,17 @@ public: autoPtr, sixDoFRigidBodyMotionRestraint, dictionary, - (const dictionary& sDoFRBMRCoeffs), - (sDoFRBMRCoeffs) + (const dictionary& sDoFRBMRDict), + (sDoFRBMRDict) ); // Constructors - //- Construct from the sDoFRBMRCoeffs dictionary and Time + //- Construct from the sDoFRBMRDict dictionary and Time sixDoFRigidBodyMotionRestraint ( - const dictionary& sDoFRBMRCoeffs + const dictionary& sDoFRBMRDict ); //- Construct and return a clone @@ -105,10 +105,10 @@ public: // Selectors - //- Select constructed from the sDoFRBMRCoeffs dictionary and Time + //- Select constructed from the sDoFRBMRDict dictionary and Time static autoPtr New ( - const dictionary& sDoFRBMRCoeffs + const dictionary& sDoFRBMRDict ); @@ -130,7 +130,7 @@ public: ) const = 0; //- Update properties from given dictionary - virtual bool read(const dictionary& sDoFRBMRCoeffs) = 0; + virtual bool read(const dictionary& sDoFRBMRDict) = 0; }; From f026a5af0ea0cc4fc0423ea0e1d0445b19ef1039 Mon Sep 17 00:00:00 2001 From: graham Date: Wed, 27 Jan 2010 18:31:55 +0000 Subject: [PATCH 05/14] sixDoFRigidBody: adding constraints. Added force to fixedPoint constraint. Moved application of rotation matrices to function. Implemented predictedPosition function. Added maximum iteration check and under-relaxation variable. --- .../sixDoFRigidBodyMotion.C | 90 ++++++++++++------- .../sixDoFRigidBodyMotion.H | 15 +++- .../fixedPoint/fixedPoint.C | 28 +++++- .../fixedPoint/fixedPoint.H | 4 +- .../sixDoFRigidBodyMotionConstraint.C | 6 +- .../sixDoFRigidBodyMotionConstraint.H | 3 + .../sixDoFRigidBodyMotionI.H | 45 +++++++++- 7 files changed, 150 insertions(+), 41 deletions(-) diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C index 0eef0872e8..cf5f1f95af 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C @@ -71,13 +71,26 @@ void Foam::sixDoFRigidBodyMotion::applyConstraints(scalar deltaT) do { - converged = true; + iter++; - Info<< "Iteration " << iter << endl; + if (iter > maxConstraintIters_) + { + FatalErrorIn + ( + "Foam::sixDoFRigidBodyMotion::applyConstraints" + "(scalar deltaT)" + ) + << nl << "Maximum number of constraint iterations (" + << maxConstraintIters_ << ") exceeded." << nl + << exit(FatalError); + + } + + converged = true; forAll(constraints_, cI) { - Info<< "Constraint " << cI << endl; + // Info<< "Constraint " << cI << endl; // constraint position point cP = vector::zero; @@ -98,11 +111,27 @@ void Foam::sixDoFRigidBodyMotion::applyConstraints(scalar deltaT) cF, cM ); + + // Accumulate constraint force + cFA += cF; + + // Accumulate constraint moment + cMA += cM + ((cP - centreOfMass()) ^ cF); } - iter++; - } while(!converged); + + Info<< "Constraints converged in " << iter << " iterations" << nl + << "Constraint force: " << cFA << nl + << "Constraint moment: " << cMA + << endl; + + // Add the constrain forces and moments to the motion state variables + a() += cFA/mass_; + + // The moment of constraint forces has already been added + // during accumulation + tau() += Q().T() & cMA; } } @@ -114,6 +143,7 @@ Foam::sixDoFRigidBodyMotion::sixDoFRigidBodyMotion() motionState_(), restraints_(), constraints_(), + maxConstraintIters_(0), refCentreOfMass_(vector::zero), momentOfInertia_(diagTensor::one*VSMALL), mass_(VSMALL) @@ -144,6 +174,7 @@ Foam::sixDoFRigidBodyMotion::sixDoFRigidBodyMotion ), restraints_(), constraints_(), + maxConstraintIters_(0), refCentreOfMass_(refCentreOfMass), momentOfInertia_(momentOfInertia), mass_(mass) @@ -155,6 +186,7 @@ Foam::sixDoFRigidBodyMotion::sixDoFRigidBodyMotion(const dictionary& dict) motionState_(dict), restraints_(), constraints_(), + maxConstraintIters_(0), refCentreOfMass_(dict.lookupOrDefault("refCentreOfMass", centreOfMass())), momentOfInertia_(dict.lookup("momentOfInertia")), mass_(readScalar(dict.lookup("mass"))) @@ -173,6 +205,7 @@ Foam::sixDoFRigidBodyMotion::sixDoFRigidBodyMotion motionState_(sDoFRBM.motionState()), restraints_(sDoFRBM.restraints()), constraints_(sDoFRBM.constraints()), + maxConstraintIters_(sDoFRBM.maxConstraintIters()), refCentreOfMass_(sDoFRBM.refCentreOfMass()), momentOfInertia_(sDoFRBM.momentOfInertia()), mass_(sDoFRBM.mass()) @@ -242,15 +275,21 @@ void Foam::sixDoFRigidBodyMotion::addConstraints constraints_.set ( - i, + i++, sixDoFRigidBodyMotionConstraint::New(iter().dict()) ); } - - i++; } constraints_.setSize(i); + + if (constraints_.size()) + { + maxConstraintIters_ = readLabel + ( + constraintDict.lookup("maxIterations") + ); + } } } @@ -274,27 +313,7 @@ void Foam::sixDoFRigidBodyMotion::updatePosition // Leapfrog orientation adjustment - tensor R; - - R = rotationTensorX(0.5*deltaT*pi().x()/momentOfInertia_.xx()); - pi() = pi() & R; - Q() = Q() & R; - - R = rotationTensorY(0.5*deltaT*pi().y()/momentOfInertia_.yy()); - pi() = pi() & R; - Q() = Q() & R; - - R = rotationTensorZ(deltaT*pi().z()/momentOfInertia_.zz()); - pi() = pi() & R; - Q() = Q() & R; - - R = rotationTensorY(0.5*deltaT*pi().y()/momentOfInertia_.yy()); - pi() = pi() & R; - Q() = Q() & R; - - R = rotationTensorX(0.5*deltaT*pi().x()/momentOfInertia_.xx()); - pi() = pi() & R; - Q() = Q() & R; + rotate(Q(), pi(), deltaT); } Pstream::scatter(motionState_); @@ -365,8 +384,17 @@ Foam::point Foam::sixDoFRigidBodyMotion::predictedPosition scalar deltaT ) const { - Info<< "predictedPosition NOT IMPLEMENTED" << endl; - return pt; + vector vTemp = v() + deltaT*(a() + deltaForce/mass_); + + vector piTemp = pi() + deltaT*(tau() + (Q().T() & deltaMoment)); + + point centreOfMassTemp = centreOfMass() + deltaT*vTemp; + + tensor QTemp = Q(); + + rotate(QTemp, piTemp, deltaT); + + return (centreOfMassTemp + (QTemp & (pt - refCentreOfMass_))); } diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.H index 4b1c724414..fd3078ed9e 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.H +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.H @@ -94,6 +94,10 @@ class sixDoFRigidBodyMotion //- Constaints on the motion PtrList constraints_; + //- Maximum number of iterations allowed to attempt to obey + // constraints + label maxConstraintIters_; + //- Centre of mass of reference state point refCentreOfMass_; @@ -118,6 +122,9 @@ class sixDoFRigidBodyMotion // frame z-axis by the given angle inline tensor rotationTensorZ(scalar deltaT) const; + //- Apply rotation tensors to Q for the given torque (pi) and deltaT + inline void rotate(tensor& Q, vector& pi, scalar deltaT) const; + //- Apply the restraints to the object void applyRestraints(); @@ -140,6 +147,10 @@ class sixDoFRigidBodyMotion inline const PtrList& constraints() const; + //- Return access to the maximum allowed number of + // constraint iterations + inline label maxConstraintIters() const; + //- Return access to the centre of mass inline const point& refCentreOfMass() const; @@ -255,11 +266,11 @@ public: //- Transform the given reference state pointField by the // current motion state - inline tmp currentPosition(const pointField& pts) const; + inline tmp currentPosition(const pointField& refPts) const; //- Transform the given reference state point by the current // motion state - inline point currentPosition(const point& pt) const; + inline point currentPosition(const point& refPt) const; //- Predict the position of the supplied point after deltaT // given the current motion state and the additional supplied diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPoint/fixedPoint.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPoint/fixedPoint.C index 7ff526fe07..cfe8b5421d 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPoint/fixedPoint.C +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPoint/fixedPoint.C @@ -86,11 +86,35 @@ bool Foam::sixDoFRigidBodyMotionConstraints::fixedPoint::constrain deltaT ); + constraintPosition = motion.currentPosition(fixedPoint_); + + // Info<< "current position " << constraintPosition << nl + // << "next predictedPosition " << predictedPosition + // << endl; + vector error = predictedPosition - fixedPoint_; - Info<< error << endl; + // Info<< "error " << error << endl; - return true; + // Correction force derived from Lagrange multiplier: + // G = -lambda*grad(sigma) + // where + // sigma = mag(error) = 0 + // so + // grad(sigma) = error/mag(error) + // Solving for lambda using the SHAKE methodology gives + // lambda = mass*mag(error)/sqr(deltaT) + // This is only strictly applicable (i.e. will converge in one + // iteration) to constraints at the centre of mass. Everything + // else will need to iterate, and may need under-relaxed to be + // stable. + + constraintForceIncrement = + -relaxationFactor_*error*motion.mass()/sqr(deltaT); + + constraintMomentIncrement = vector::zero; + + return (mag(error) < tolerance_); } diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPoint/fixedPoint.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPoint/fixedPoint.H index 9619d8e72f..59b5c35c43 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPoint/fixedPoint.H +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPoint/fixedPoint.H @@ -58,7 +58,9 @@ class fixedPoint // Private data //- Point which is rigidly attached to the body and constrains - // it so that this point remains fixed. + // it so that this point remains fixed. This serves as the + // reference point for displacements as well as the target + // position. point fixedPoint_; diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint.C index bb8c50b3a5..7c22078878 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint.C +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint.C @@ -47,7 +47,11 @@ Foam::sixDoFRigidBodyMotionConstraint::sixDoFRigidBodyMotionConstraint + "Coeffs" ) ), - tolerance_(readScalar(sDoFRBMCDict.lookup("tolerance"))) + tolerance_(readScalar(sDoFRBMCDict.lookup("tolerance"))), + relaxationFactor_ + ( + sDoFRBMCDict.lookupOrDefault("relaxationFactor", 1) + ) {} diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint.H index be240dce2b..0b5fa0bc79 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint.H +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint.H @@ -77,6 +77,9 @@ protected: // absolute distance or angle. scalar tolerance_; + //- Relaxation factor for solution, default to one + scalar relaxationFactor_; + public: diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionI.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionI.H index 5b0d607ef4..146282749e 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionI.H +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionI.H @@ -62,6 +62,37 @@ Foam::sixDoFRigidBodyMotion::rotationTensorZ(scalar phi) const } +inline void Foam::sixDoFRigidBodyMotion::rotate +( + tensor& Q, + vector& pi, + scalar deltaT +) const +{ + tensor R; + + R = rotationTensorX(0.5*deltaT*pi.x()/momentOfInertia_.xx()); + pi = pi & R; + Q = Q & R; + + R = rotationTensorY(0.5*deltaT*pi.y()/momentOfInertia_.yy()); + pi = pi & R; + Q = Q & R; + + R = rotationTensorZ(deltaT*pi.z()/momentOfInertia_.zz()); + pi = pi & R; + Q = Q & R; + + R = rotationTensorY(0.5*deltaT*pi.y()/momentOfInertia_.yy()); + pi = pi & R; + Q = Q & R; + + R = rotationTensorX(0.5*deltaT*pi.x()/momentOfInertia_.xx()); + pi = pi & R; + Q = Q & R; +} + + inline const Foam::sixDoFRigidBodyMotionState& Foam::sixDoFRigidBodyMotion::motionState() const { @@ -83,6 +114,12 @@ Foam::sixDoFRigidBodyMotion::constraints() const } +inline Foam::label Foam::sixDoFRigidBodyMotion::maxConstraintIters() const +{ + return maxConstraintIters_; +} + + inline const Foam::point& Foam::sixDoFRigidBodyMotion::refCentreOfMass() const { return refCentreOfMass_; @@ -171,18 +208,18 @@ inline Foam::vector& Foam::sixDoFRigidBodyMotion::tau() // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // inline Foam::tmp -Foam::sixDoFRigidBodyMotion::currentPosition(const pointField& pts) const +Foam::sixDoFRigidBodyMotion::currentPosition(const pointField& refPts) const { - return (centreOfMass() + (Q() & (pts - refCentreOfMass_))); + return (centreOfMass() + (Q() & (refPts - refCentreOfMass_))); } inline Foam::point Foam::sixDoFRigidBodyMotion::currentPosition ( - const point& pt + const point& refPt ) const { - return (centreOfMass() + (Q() & (pt - refCentreOfMass_))); + return (centreOfMass() + (Q() & (refPt - refCentreOfMass_))); } From d5829988d80578d4ba2ef48aa6a26e29f419f97c Mon Sep 17 00:00:00 2001 From: graham Date: Thu, 28 Jan 2010 13:56:13 +0000 Subject: [PATCH 06/14] plane class: adding normalisation of normal vector for vector only constructor. --- .../meshes/primitiveShapes/plane/plane.C | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/OpenFOAM/meshes/primitiveShapes/plane/plane.C b/src/OpenFOAM/meshes/primitiveShapes/plane/plane.C index 2e90e4d62c..6f711cc603 100644 --- a/src/OpenFOAM/meshes/primitiveShapes/plane/plane.C +++ b/src/OpenFOAM/meshes/primitiveShapes/plane/plane.C @@ -128,7 +128,20 @@ Foam::plane::plane(const vector& normalVector) : unitVector_(normalVector), basePoint_(vector::zero) -{} +{ + scalar magUnitVector(mag(unitVector_)); + + if (magUnitVector > VSMALL) + { + unitVector_ /= magUnitVector; + } + else + { + FatalErrorIn("plane::plane(const point&, const vector&)") + << "plane normal has zero length" + << abort(FatalError); + } +} // Construct from point and normal vector @@ -146,8 +159,8 @@ Foam::plane::plane(const point& basePoint, const vector& normalVector) else { FatalErrorIn("plane::plane(const point&, const vector&)") - << "plane normal has got zero length" - << abort(FatalError); + << "plane normal has zero length" + << abort(FatalError); } } @@ -217,8 +230,8 @@ Foam::plane::plane(const dictionary& dict) "plane::plane(const dictionary&)", dict ) - << "Invalid plane type: " << planeType - << abort(FatalIOError); + << "Invalid plane type: " << planeType + << abort(FatalIOError); } } @@ -238,7 +251,7 @@ Foam::plane::plane(Istream& is) else { FatalErrorIn("plane::plane(Istream& is)") - << "plane normal has got zero length" + << "plane normal has zero length" << abort(FatalError); } } From c6701df1f69612ce3345c4924f71dc9548879898 Mon Sep 17 00:00:00 2001 From: graham Date: Thu, 28 Jan 2010 15:27:08 +0000 Subject: [PATCH 07/14] sixDoFRigidBody: adding constraints. Adding fixedPlane and fixedLine constraints. --- .../functionObjects/forces/Make/files | 2 + .../sixDoFRigidBodyMotion.C | 2 +- .../fixedLine/fixedLine.C | 145 ++++++++++++++++++ .../fixedLine/fixedLine.H | 127 +++++++++++++++ .../fixedPlane/fixedPlane.C | 128 ++++++++++++++++ .../fixedPlane/fixedPlane.H | 125 +++++++++++++++ .../fixedPoint/fixedPoint.C | 2 +- .../fixedPoint/fixedPoint.H | 2 +- 8 files changed, 530 insertions(+), 3 deletions(-) create mode 100644 src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedLine/fixedLine.C create mode 100644 src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedLine/fixedLine.H create mode 100644 src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPlane/fixedPlane.C create mode 100644 src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPlane/fixedPlane.H diff --git a/src/postProcessing/functionObjects/forces/Make/files b/src/postProcessing/functionObjects/forces/Make/files index a7541d14c0..0f366f30ad 100644 --- a/src/postProcessing/functionObjects/forces/Make/files +++ b/src/postProcessing/functionObjects/forces/Make/files @@ -22,6 +22,8 @@ sDoFRBMC = $(sDoFRBM)/sixDoFRigidBodyMotionConstraint $(sDoFRBMC)/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint.C $(sDoFRBMC)/sixDoFRigidBodyMotionConstraint/newSixDoFRigidBodyMotionConstraint.C $(sDoFRBMC)/fixedPoint/fixedPoint.C +$(sDoFRBMC)/fixedPlane/fixedPlane.C +$(sDoFRBMC)/fixedLine/fixedLine.C pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyDisplacementPointPatchVectorField.C pointPatchFields/derived/uncoupledSixDoFRigidBodyDisplacement/uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField.C diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C index cf5f1f95af..76b376d3b5 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C @@ -90,7 +90,7 @@ void Foam::sixDoFRigidBodyMotion::applyConstraints(scalar deltaT) forAll(constraints_, cI) { - // Info<< "Constraint " << cI << endl; + Info<< nl << "Constraint " << cI << endl; // constraint position point cP = vector::zero; diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedLine/fixedLine.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedLine/fixedLine.C new file mode 100644 index 0000000000..290531ba9e --- /dev/null +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedLine/fixedLine.C @@ -0,0 +1,145 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-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 + +\*---------------------------------------------------------------------------*/ + +#include "fixedLine.H" +#include "addToRunTimeSelectionTable.H" +#include "sixDoFRigidBodyMotion.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace sixDoFRigidBodyMotionConstraints +{ + defineTypeNameAndDebug(fixedLine, 0); + addToRunTimeSelectionTable + ( + sixDoFRigidBodyMotionConstraint, + fixedLine, + dictionary + ); +}; +}; + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::sixDoFRigidBodyMotionConstraints::fixedLine::fixedLine +( + const dictionary& sDoFRBMCDict +) +: + sixDoFRigidBodyMotionConstraint(sDoFRBMCDict), + refPt_(), + dir_() +{ + read(sDoFRBMCDict); +} + + +// * * * * * * * * * * * * * * * * Destructors * * * * * * * * * * * * * * * // + +Foam::sixDoFRigidBodyMotionConstraints::fixedLine::~fixedLine() +{} + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +bool Foam::sixDoFRigidBodyMotionConstraints::fixedLine::constrain +( + const sixDoFRigidBodyMotion& motion, + const vector& existingConstraintForce, + const vector& existingConstraintMoment, + scalar deltaT, + vector& constraintPosition, + vector& constraintForceIncrement, + vector& constraintMomentIncrement +) const +{ + point predictedPosition = motion.predictedPosition + ( + refPt_, + existingConstraintForce, + existingConstraintMoment, + deltaT + ); + + constraintPosition = motion.currentPosition(refPt_); + + Info<< "current position " << constraintPosition << nl + << "next predictedPosition " << predictedPosition + << endl; + + // Vector from reference point to predicted point + vector rC = predictedPosition - refPt_; + + vector error = rC - ((rC) & dir_)*dir_; + + Info<< "error " << error << endl; + + constraintForceIncrement = + -relaxationFactor_*error*motion.mass()/sqr(deltaT); + + constraintMomentIncrement = vector::zero; + + return (mag(error) < tolerance_); +} + + +bool Foam::sixDoFRigidBodyMotionConstraints::fixedLine::read +( + const dictionary& sDoFRBMCDict +) +{ + sixDoFRigidBodyMotionConstraint::read(sDoFRBMCDict); + + sDoFRBMCCoeffs_.lookup("refPoint") >> refPt_; + + sDoFRBMCCoeffs_.lookup("direction") >> dir_; + + scalar magDir(mag(dir_)); + + if (magDir > VSMALL) + { + dir_ /= magDir; + } + else + { + FatalErrorIn + ( + "Foam::sixDoFRigidBodyMotionConstraints::fixedLine::read" + "(" + "const dictionary& sDoFRBMCDict" + ")" + ) + << "line direction has zero length" + << abort(FatalError); + } + + return true; +} + +// ************************************************************************* // diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedLine/fixedLine.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedLine/fixedLine.H new file mode 100644 index 0000000000..01cc8ff52f --- /dev/null +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedLine/fixedLine.H @@ -0,0 +1,127 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-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 + Foam::sixDoFRigidBodyMotionConstraints::fixedLine + +Description + sixDoFRigidBodyMotionConstraint. Reference point may only move + along a line. + +SourceFiles + fixedLine.C + +\*---------------------------------------------------------------------------*/ + +#ifndef fixedLine_H +#define fixedLine_H + +#include "sixDoFRigidBodyMotionConstraint.H" +#include "point.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +namespace sixDoFRigidBodyMotionConstraints +{ + +/*---------------------------------------------------------------------------*\ + Class fixedLine Declaration +\*---------------------------------------------------------------------------*/ + +class fixedLine +: + public sixDoFRigidBodyMotionConstraint +{ + // Private data + + //- Reference point for the constraining line + point refPt_; + + //- Direction of the constraining line + vector dir_; + + +public: + + //- Runtime type information + TypeName("fixedLine"); + + + // Constructors + + //- Construct from components + fixedLine + ( + const dictionary& sDoFRBMCDict + ); + + //- Construct and return a clone + virtual autoPtr clone() const + { + return autoPtr + ( + new fixedLine(*this) + ); + } + + + // Destructor + + virtual ~fixedLine(); + + + // Member Functions + + //- Calculate the constraint position, force and moment. + // Global reference frame vectors. Returns boolean stating + // whether the constraint been converged to tolerance. + virtual bool constrain + ( + const sixDoFRigidBodyMotion& motion, + const vector& existingConstraintForce, + const vector& existingConstraintMoment, + scalar deltaT, + vector& constraintPosition, + vector& constraintForceIncrement, + vector& constraintMomentIncrement + ) const; + + //- Update properties from given dictionary + virtual bool read(const dictionary& sDoFRBMCCoeff); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace solidBodyMotionFunctions +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPlane/fixedPlane.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPlane/fixedPlane.C new file mode 100644 index 0000000000..29734967bd --- /dev/null +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPlane/fixedPlane.C @@ -0,0 +1,128 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-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 + +\*---------------------------------------------------------------------------*/ + +#include "fixedPlane.H" +#include "addToRunTimeSelectionTable.H" +#include "sixDoFRigidBodyMotion.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace sixDoFRigidBodyMotionConstraints +{ + defineTypeNameAndDebug(fixedPlane, 0); + addToRunTimeSelectionTable + ( + sixDoFRigidBodyMotionConstraint, + fixedPlane, + dictionary + ); +}; +}; + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::sixDoFRigidBodyMotionConstraints::fixedPlane::fixedPlane +( + const dictionary& sDoFRBMCDict +) +: + sixDoFRigidBodyMotionConstraint(sDoFRBMCDict), + fixedPlane_(vector::one) +{ + read(sDoFRBMCDict); +} + + +// * * * * * * * * * * * * * * * * Destructors * * * * * * * * * * * * * * * // + +Foam::sixDoFRigidBodyMotionConstraints::fixedPlane::~fixedPlane() +{} + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +bool Foam::sixDoFRigidBodyMotionConstraints::fixedPlane::constrain +( + const sixDoFRigidBodyMotion& motion, + const vector& existingConstraintForce, + const vector& existingConstraintMoment, + scalar deltaT, + vector& constraintPosition, + vector& constraintForceIncrement, + vector& constraintMomentIncrement +) const +{ + const point& refPt = fixedPlane_.refPoint(); + + const vector& n = fixedPlane_.normal(); + + point predictedPosition = motion.predictedPosition + ( + refPt, + existingConstraintForce, + existingConstraintMoment, + deltaT + ); + + constraintPosition = motion.currentPosition(refPt); + + Info<< "current position " << constraintPosition << nl + << "next predictedPosition " << predictedPosition + << endl; + + vector error = ((predictedPosition - refPt) & n)*n; + + Info<< "error " << error << endl; + + constraintForceIncrement = + -relaxationFactor_*error*motion.mass()/sqr(deltaT); + + constraintMomentIncrement = vector::zero; + + return (mag(error) < tolerance_); +} + + +bool Foam::sixDoFRigidBodyMotionConstraints::fixedPlane::read +( + const dictionary& sDoFRBMCDict +) +{ + sixDoFRigidBodyMotionConstraint::read(sDoFRBMCDict); + + point refPt = sDoFRBMCCoeffs_.lookup("refPoint"); + + vector normal = sDoFRBMCCoeffs_.lookup("normal"); + + fixedPlane_ = plane(refPt, normal); + + return true; +} + +// ************************************************************************* // diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPlane/fixedPlane.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPlane/fixedPlane.H new file mode 100644 index 0000000000..45f35dbbb4 --- /dev/null +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPlane/fixedPlane.H @@ -0,0 +1,125 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-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 + Foam::sixDoFRigidBodyMotionConstraints::fixedPlane + +Description + sixDoFRigidBodyMotionConstraint. Reference point may only move + along a plane. + +SourceFiles + fixedPlane.C + +\*---------------------------------------------------------------------------*/ + +#ifndef fixedPlane_H +#define fixedPlane_H + +#include "sixDoFRigidBodyMotionConstraint.H" +#include "plane.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +namespace sixDoFRigidBodyMotionConstraints +{ + +/*---------------------------------------------------------------------------*\ + Class fixedPlane Declaration +\*---------------------------------------------------------------------------*/ + +class fixedPlane +: + public sixDoFRigidBodyMotionConstraint +{ + // Private data + + //- Plane which the transformed reference point is constrained + // to move along + plane fixedPlane_; + + +public: + + //- Runtime type information + TypeName("fixedPlane"); + + + // Constructors + + //- Construct from components + fixedPlane + ( + const dictionary& sDoFRBMCDict + ); + + //- Construct and return a clone + virtual autoPtr clone() const + { + return autoPtr + ( + new fixedPlane(*this) + ); + } + + + // Destructor + + virtual ~fixedPlane(); + + + // Member Functions + + //- Calculate the constraint position, force and moment. + // Global reference frame vectors. Returns boolean stating + // whether the constraint been converged to tolerance. + virtual bool constrain + ( + const sixDoFRigidBodyMotion& motion, + const vector& existingConstraintForce, + const vector& existingConstraintMoment, + scalar deltaT, + vector& constraintPosition, + vector& constraintForceIncrement, + vector& constraintMomentIncrement + ) const; + + //- Update properties from given dictionary + virtual bool read(const dictionary& sDoFRBMCCoeff); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace solidBodyMotionFunctions +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPoint/fixedPoint.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPoint/fixedPoint.C index cfe8b5421d..3862f16e65 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPoint/fixedPoint.C +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPoint/fixedPoint.C @@ -53,7 +53,7 @@ Foam::sixDoFRigidBodyMotionConstraints::fixedPoint::fixedPoint ) : sixDoFRigidBodyMotionConstraint(sDoFRBMCDict), - fixedPoint_() + fixedPoint_(sDoFRBMCCoeffs_.lookup("fixedPoint")) { read(sDoFRBMCDict); } diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPoint/fixedPoint.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPoint/fixedPoint.H index 59b5c35c43..933ba2db09 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPoint/fixedPoint.H +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPoint/fixedPoint.H @@ -48,7 +48,7 @@ namespace sixDoFRigidBodyMotionConstraints { /*---------------------------------------------------------------------------*\ - Class fixedPoint Declaration + Class fixedPoint Declaration \*---------------------------------------------------------------------------*/ class fixedPoint From 79a14c4b7c2b8b03e2e64653fb687cb5c35b3863 Mon Sep 17 00:00:00 2001 From: graham Date: Thu, 28 Jan 2010 16:35:19 +0000 Subject: [PATCH 08/14] BUG: sixDoFRigidBodyMotion, calling boolean function along with boolean test was not actually calling the function. Probably optimised out. --- .../sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C index 76b376d3b5..cdfe5ffc22 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C @@ -61,7 +61,7 @@ void Foam::sixDoFRigidBodyMotion::applyConstraints(scalar deltaT) { label iter = 0; - bool converged = true; + bool allConverged = true; // constraint force accumulator vector cFA = vector::zero; @@ -86,7 +86,7 @@ void Foam::sixDoFRigidBodyMotion::applyConstraints(scalar deltaT) } - converged = true; + allConverged = true; forAll(constraints_, cI) { @@ -101,7 +101,7 @@ void Foam::sixDoFRigidBodyMotion::applyConstraints(scalar deltaT) // constraint moment vector cM = vector::zero; - converged = converged && constraints_[cI].constrain + bool constraintConverged = constraints_[cI].constrain ( *this, cFA, @@ -112,6 +112,8 @@ void Foam::sixDoFRigidBodyMotion::applyConstraints(scalar deltaT) cM ); + allConverged = allConverged && constraintConverged; + // Accumulate constraint force cFA += cF; @@ -119,7 +121,7 @@ void Foam::sixDoFRigidBodyMotion::applyConstraints(scalar deltaT) cMA += cM + ((cP - centreOfMass()) ^ cF); } - } while(!converged); + } while(!allConverged); Info<< "Constraints converged in " << iter << " iterations" << nl << "Constraint force: " << cFA << nl From 8f443575554f70c69f6b2786e1453839b8268713 Mon Sep 17 00:00:00 2001 From: graham Date: Fri, 29 Jan 2010 15:20:42 +0000 Subject: [PATCH 09/14] ENH: sixDoFRigidBodyMotion. Adding linearSphericalAngularSpring restraint. Moving maximum iteration FatalErrorIn check after constraint while loop. Adding currentOrientation function to give access to Q, but safely and with a more descriptive name for the function. --- .../functionObjects/forces/Make/files | 1 + .../sixDoFRigidBodyMotion.C | 44 +++--- .../sixDoFRigidBodyMotion.H | 4 + .../fixedLine/fixedLine.C | 8 +- .../fixedPlane/fixedPlane.C | 8 +- .../sixDoFRigidBodyMotionI.H | 9 ++ .../linearSphericalAngularSpring.C | 128 ++++++++++++++++++ .../linearSphericalAngularSpring.H | 125 +++++++++++++++++ 8 files changed, 297 insertions(+), 30 deletions(-) create mode 100644 src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSphericalAngularSpring/linearSphericalAngularSpring.C create mode 100644 src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSphericalAngularSpring/linearSphericalAngularSpring.H diff --git a/src/postProcessing/functionObjects/forces/Make/files b/src/postProcessing/functionObjects/forces/Make/files index 0f366f30ad..f0304ea6f0 100644 --- a/src/postProcessing/functionObjects/forces/Make/files +++ b/src/postProcessing/functionObjects/forces/Make/files @@ -16,6 +16,7 @@ sDoFRBMR = $(sDoFRBM)/sixDoFRigidBodyMotionRestraint $(sDoFRBMR)/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.C $(sDoFRBMR)/sixDoFRigidBodyMotionRestraint/newSixDoFRigidBodyMotionRestraint.C $(sDoFRBMR)/linearSpring/linearSpring.C +$(sDoFRBMR)/linearSphericalAngularSpring/linearSphericalAngularSpring.C sDoFRBMC = $(sDoFRBM)/sixDoFRigidBodyMotionConstraint diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C index cdfe5ffc22..66e76833bf 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C @@ -45,7 +45,7 @@ void Foam::sixDoFRigidBodyMotion::applyRestraints() restraints_[rI].restrain(*this, rP, rF, rM); - Info<< "Restraint " << rI << " force " << rF << endl; + // Info<< "Restraint " << rI << " force " << rF << endl; a() += rF/mass_; @@ -71,26 +71,11 @@ void Foam::sixDoFRigidBodyMotion::applyConstraints(scalar deltaT) do { - iter++; - - if (iter > maxConstraintIters_) - { - FatalErrorIn - ( - "Foam::sixDoFRigidBodyMotion::applyConstraints" - "(scalar deltaT)" - ) - << nl << "Maximum number of constraint iterations (" - << maxConstraintIters_ << ") exceeded." << nl - << exit(FatalError); - - } - allConverged = true; forAll(constraints_, cI) { - Info<< nl << "Constraint " << cI << endl; + // Info<< nl << "Constraint " << cI << endl; // constraint position point cP = vector::zero; @@ -121,12 +106,27 @@ void Foam::sixDoFRigidBodyMotion::applyConstraints(scalar deltaT) cMA += cM + ((cP - centreOfMass()) ^ cF); } - } while(!allConverged); + } while(!allConverged && ++iter < maxConstraintIters_); - Info<< "Constraints converged in " << iter << " iterations" << nl - << "Constraint force: " << cFA << nl - << "Constraint moment: " << cMA - << endl; + if (iter >= maxConstraintIters_) + { + FatalErrorIn + ( + "Foam::sixDoFRigidBodyMotion::applyConstraints" + "(scalar deltaT)" + ) + << nl << "Maximum number of sixDoFRigidBodyMotion constraint " + << "iterations (" << maxConstraintIters_ << ") exceeded." << nl + << exit(FatalError); + } + else + { + Info<< "sixDoFRigidBodyMotion constraints converged in " + << iter << " iterations" << nl + // << "Constraint force: " << cFA << nl + // << "Constraint moment: " << cMA + << endl; + } // Add the constrain forces and moments to the motion state variables a() += cFA/mass_; diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.H index fd3078ed9e..343403eb0a 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.H +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.H @@ -272,6 +272,10 @@ public: // motion state inline point currentPosition(const point& refPt) const; + //- Transform the given reference state direction by the current + // motion state + inline point currentOrientation(const vector& refDir) const; + //- Predict the position of the supplied point after deltaT // given the current motion state and the additional supplied // force and moment diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedLine/fixedLine.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedLine/fixedLine.C index 290531ba9e..b5cee9ecc2 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedLine/fixedLine.C +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedLine/fixedLine.C @@ -89,16 +89,16 @@ bool Foam::sixDoFRigidBodyMotionConstraints::fixedLine::constrain constraintPosition = motion.currentPosition(refPt_); - Info<< "current position " << constraintPosition << nl - << "next predictedPosition " << predictedPosition - << endl; + // Info<< "current position " << constraintPosition << nl + // << "next predictedPosition " << predictedPosition + // << endl; // Vector from reference point to predicted point vector rC = predictedPosition - refPt_; vector error = rC - ((rC) & dir_)*dir_; - Info<< "error " << error << endl; + // Info<< "error " << error << endl; constraintForceIncrement = -relaxationFactor_*error*motion.mass()/sqr(deltaT); diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPlane/fixedPlane.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPlane/fixedPlane.C index 29734967bd..fad22e7c13 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPlane/fixedPlane.C +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPlane/fixedPlane.C @@ -92,13 +92,13 @@ bool Foam::sixDoFRigidBodyMotionConstraints::fixedPlane::constrain constraintPosition = motion.currentPosition(refPt); - Info<< "current position " << constraintPosition << nl - << "next predictedPosition " << predictedPosition - << endl; + // Info<< "current position " << constraintPosition << nl + // << "next predictedPosition " << predictedPosition + // << endl; vector error = ((predictedPosition - refPt) & n)*n; - Info<< "error " << error << endl; + // Info<< "error " << error << endl; constraintForceIncrement = -relaxationFactor_*error*motion.mass()/sqr(deltaT); diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionI.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionI.H index 146282749e..18607cc86f 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionI.H +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionI.H @@ -223,6 +223,15 @@ inline Foam::point Foam::sixDoFRigidBodyMotion::currentPosition } +inline Foam::point Foam::sixDoFRigidBodyMotion::currentOrientation +( + const vector& refDir +) const +{ + return (Q() & refDir); +} + + inline Foam::vector Foam::sixDoFRigidBodyMotion::omega() const { return Q() & (inv(momentOfInertia_) & pi()); diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSphericalAngularSpring/linearSphericalAngularSpring.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSphericalAngularSpring/linearSphericalAngularSpring.C new file mode 100644 index 0000000000..0d7d2bddca --- /dev/null +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSphericalAngularSpring/linearSphericalAngularSpring.C @@ -0,0 +1,128 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-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 + +\*---------------------------------------------------------------------------*/ + +#include "linearSphericalAngularSpring.H" +#include "addToRunTimeSelectionTable.H" +#include "sixDoFRigidBodyMotion.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace sixDoFRigidBodyMotionRestraints +{ + defineTypeNameAndDebug(linearSphericalAngularSpring, 0); + addToRunTimeSelectionTable + ( + sixDoFRigidBodyMotionRestraint, + linearSphericalAngularSpring, + dictionary + ); +}; +}; + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::sixDoFRigidBodyMotionRestraints::linearSphericalAngularSpring:: +linearSphericalAngularSpring +( + const dictionary& sDoFRBMRDict +) +: + sixDoFRigidBodyMotionRestraint(sDoFRBMRDict), + refDir_(), + stiffness_(), + damping_() +{ + read(sDoFRBMRDict); +} + + +// * * * * * * * * * * * * * * * * Destructors * * * * * * * * * * * * * * * // + +Foam::sixDoFRigidBodyMotionRestraints::linearSphericalAngularSpring:: +~linearSphericalAngularSpring() +{} + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +void +Foam::sixDoFRigidBodyMotionRestraints::linearSphericalAngularSpring::restrain +( + const sixDoFRigidBodyMotion& motion, + vector& restraintPosition, + vector& restraintForce, + vector& restraintMoment +) const +{ + vector curDir = motion.currentOrientation(refDir_); + + vector a = refDir_ ^ curDir; + + scalar magA = mag(a); + + scalar theta = 0; + + if (magA > VSMALL) + { + a /= magA; + + theta = acos(curDir & refDir_); + } + else + { + a = vector::zero; + } + + restraintMoment = -stiffness_*theta*a - damping_*motion.omega(); + + restraintForce = vector::zero; + + // Not needed to be altered as restraintForce is zero, but set to + // centre of mass to be sure of no spurious moment + restraintPosition = motion.centreOfMass(); +} + + +bool Foam::sixDoFRigidBodyMotionRestraints::linearSphericalAngularSpring ::read +( + const dictionary& sDoFRBMRDict +) +{ + sixDoFRigidBodyMotionRestraint::read(sDoFRBMRDict); + + sDoFRBMRCoeffs_.lookup("referenceDirection") >> refDir_; + + sDoFRBMRCoeffs_.lookup("stiffness") >> stiffness_; + + sDoFRBMRCoeffs_.lookup("damping") >> damping_; + + return true; +} + +// ************************************************************************* // diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSphericalAngularSpring/linearSphericalAngularSpring.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSphericalAngularSpring/linearSphericalAngularSpring.H new file mode 100644 index 0000000000..d43b264cf9 --- /dev/null +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSphericalAngularSpring/linearSphericalAngularSpring.H @@ -0,0 +1,125 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-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 + Foam::sixDoFRigidBodyMotionRestraints::linearSphericalAngularSpring + +Description + sixDoFRigidBodyMotionRestraints model. Linear spherical angular spring. + +SourceFiles + linearSphericalAngularSpring.C + +\*---------------------------------------------------------------------------*/ + +#ifndef linearSphericalAngularSpring_H +#define linearSphericalAngularSpring_H + +#include "sixDoFRigidBodyMotionRestraint.H" +#include "point.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +namespace sixDoFRigidBodyMotionRestraints +{ + +/*---------------------------------------------------------------------------*\ + Class linearSphericalAngularSpring Declaration +\*---------------------------------------------------------------------------*/ + +class linearSphericalAngularSpring +: + public sixDoFRigidBodyMotionRestraint +{ + // Private data + + // Reference direction there is no spring reaction torque + vector refDir_; + + //- Spring stiffness coefficient (Nm/rad) + scalar stiffness_; + + //- Damping coefficient (Nms/rad) + scalar damping_; + + +public: + + //- Runtime type information + TypeName("linearSphericalAngularSpring"); + + + // Constructors + + //- Construct from components + linearSphericalAngularSpring + ( + const dictionary& sDoFRBMRDict + ); + + //- Construct and return a clone + virtual autoPtr clone() const + { + return autoPtr + ( + new linearSphericalAngularSpring(*this) + ); + } + + + // Destructor + + virtual ~linearSphericalAngularSpring(); + + + // Member Functions + + //- Calculate the restraint position, force and moment. + // Global reference frame vectors. + virtual void restrain + ( + const sixDoFRigidBodyMotion& motion, + vector& restraintPosition, + vector& restraintForce, + vector& restraintMoment + ) const; + + //- Update properties from given dictionary + virtual bool read(const dictionary& sDoFRBMRCoeff); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace solidBodyMotionFunctions +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // From 6cecf20555fd0ef11b19c3bf5ebd47cd2a45d16d Mon Sep 17 00:00:00 2001 From: graham Date: Fri, 29 Jan 2010 20:27:29 +0000 Subject: [PATCH 10/14] ENC: sixDoFRigidBodyMotion. Adding writing of restraints and constraints to dictionary. --- .../sixDoFRigidBodyMotion.C | 10 +-- .../sixDoFRigidBodyMotionConstraint.C | 7 ++ .../sixDoFRigidBodyMotionConstraint.H | 29 ++++++++ .../sixDoFRigidBodyMotionIO.C | 66 ++++++++++++++++++- .../linearSphericalAngularSpring.C | 20 ++++++ .../sixDoFRigidBodyMotionRestraint.C | 1 + .../sixDoFRigidBodyMotionRestraint.H | 18 +++++ 7 files changed, 146 insertions(+), 5 deletions(-) diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C index 66e76833bf..d2c414b055 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C @@ -45,7 +45,9 @@ void Foam::sixDoFRigidBodyMotion::applyRestraints() restraints_[rI].restrain(*this, rP, rF, rM); - // Info<< "Restraint " << rI << " force " << rF << endl; + // Info<< "Restraint " << rI << " force " << rF << nl + // << "Restraint " << rI << " moment " << rM + // << endl; a() += rF/mass_; @@ -122,9 +124,9 @@ void Foam::sixDoFRigidBodyMotion::applyConstraints(scalar deltaT) else { Info<< "sixDoFRigidBodyMotion constraints converged in " - << iter << " iterations" << nl - // << "Constraint force: " << cFA << nl - // << "Constraint moment: " << cMA + << iter << " iterations" + // << nl << "Constraint force: " << cFA << nl + // << "Constraint moment: " << cMA << endl; } diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint.C index 7c22078878..082bbb34af 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint.C +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint.C @@ -39,6 +39,7 @@ Foam::sixDoFRigidBodyMotionConstraint::sixDoFRigidBodyMotionConstraint const dictionary& sDoFRBMCDict ) : + name_(fileName(sDoFRBMCDict.name().name()).components(token::COLON).last()), sDoFRBMCCoeffs_ ( sDoFRBMCDict.subDict @@ -70,6 +71,12 @@ bool Foam::sixDoFRigidBodyMotionConstraint::read { tolerance_ = (readScalar(sDoFRBMCDict.lookup("tolerance"))); + relaxationFactor_ = sDoFRBMCDict.lookupOrDefault + ( + "relaxationFactor", + 1 + ); + sDoFRBMCCoeffs_ = sDoFRBMCDict.subDict(type() + "Coeffs"); return true; diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint.H index 0b5fa0bc79..22e5770202 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint.H +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint.H @@ -70,6 +70,9 @@ protected: // Protected data + //- Name of the constraint in dictionary + word name_; + //- Constraint model specific coefficient dictionary dictionary sDoFRBMCCoeffs_; @@ -143,6 +146,32 @@ public: //- Update properties from given dictionary virtual bool read(const dictionary& sDoFRBMCDict) = 0; + + // Access + + //- Return access to the name of the restraint + inline const word& name() const + { + return name_; + } + + // Return access to sDoFRBMCCoeffs + inline const dictionary& coeffDict() const + { + return sDoFRBMCCoeffs_; + } + + //- Return access to the tolerance + inline scalar tolerance() const + { + return tolerance_; + } + + //- Return access to the relaxationFactor + inline scalar relaxationFactor() const + { + return relaxationFactor_; + } }; diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionIO.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionIO.C index 005cbbe6aa..e8172f4183 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionIO.C +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionIO.C @@ -39,6 +39,70 @@ void Foam::sixDoFRigidBodyMotion::write(Ostream& os) const << momentOfInertia_ << token::END_STATEMENT << nl; os.writeKeyword("mass") << mass_ << token::END_STATEMENT << nl; + + if (restraints_.size()) + { + dictionary restraintsDict; + + forAll(restraints_, rI) + { + word restraintType = restraints_[rI].type(); + + dictionary restraintDict; + + restraintDict.add("sixDoFRigidBodyMotionRestraint", restraintType); + + restraintDict.add + ( + word(restraintType + "Coeffs"), restraints_[rI].coeffDict() + ); + + restraintsDict.add(restraints_[rI].name(), restraintDict); + } + + os.writeKeyword("restraints") << restraintsDict; + } + + if (constraints_.size()) + { + dictionary constraintsDict; + + constraintsDict.add("maxIterations", maxConstraintIters_); + + forAll(constraints_, rI) + { + word constraintType = constraints_[rI].type(); + + dictionary constraintDict; + + constraintDict.add + ( + "sixDoFRigidBodyMotionConstraint", + constraintType + ); + + constraintDict.add + ( + "tolerance", + constraints_[rI].tolerance() + ); + + constraintDict.add + ( + "relaxationFactor", + constraints_[rI].relaxationFactor() + ); + + constraintDict.add + ( + word(constraintType + "Coeffs"), constraints_[rI].coeffDict() + ); + + constraintsDict.add(constraints_[rI].name(), constraintDict); + } + + os.writeKeyword("constraints") << constraintsDict; + } } @@ -71,7 +135,7 @@ Foam::Ostream& Foam::operator<< os << sDoFRBM.motionState() << token::SPACE << sDoFRBM.refCentreOfMass() << token::SPACE << sDoFRBM.momentOfInertia() - << token::SPACE << sDoFRBM.mass() ; + << token::SPACE << sDoFRBM.mass(); // Check state of Ostream os.check diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSphericalAngularSpring/linearSphericalAngularSpring.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSphericalAngularSpring/linearSphericalAngularSpring.C index 0d7d2bddca..2672d2d26e 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSphericalAngularSpring/linearSphericalAngularSpring.C +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSphericalAngularSpring/linearSphericalAngularSpring.C @@ -118,6 +118,26 @@ bool Foam::sixDoFRigidBodyMotionRestraints::linearSphericalAngularSpring ::read sDoFRBMRCoeffs_.lookup("referenceDirection") >> refDir_; + scalar magRefDir(mag(refDir_)); + + if (magRefDir > VSMALL) + { + refDir_ /= magRefDir; + } + else + { + FatalErrorIn + ( + "bool Foam::sixDoFRigidBodyMotionRestraints::" + "linearSphericalAngularSpring ::read" + "(" + "const dictionary& sDoFRBMRDict" + ")" + ) + << "referenceDirection has zero length" + << abort(FatalError); + } + sDoFRBMRCoeffs_.lookup("stiffness") >> stiffness_; sDoFRBMRCoeffs_.lookup("damping") >> damping_; diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.C index 2d17503421..7cfe723c01 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.C +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.C @@ -39,6 +39,7 @@ Foam::sixDoFRigidBodyMotionRestraint::sixDoFRigidBodyMotionRestraint const dictionary& sDoFRBMRDict ) : + name_(fileName(sDoFRBMRDict.name().name()).components(token::COLON).last()), sDoFRBMRCoeffs_ ( sDoFRBMRDict.subDict diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.H index b9e0d5f0f1..1bdabb57e3 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.H +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.H @@ -70,6 +70,10 @@ protected: // Protected data + //- Name of the constraint in dictionary + word name_; + + //- Restraint model specific coefficient dictionary dictionary sDoFRBMRCoeffs_; @@ -131,6 +135,20 @@ public: //- Update properties from given dictionary virtual bool read(const dictionary& sDoFRBMRDict) = 0; + + // Access + + //- Return access to the name of the restraint + inline const word& name() const + { + return name_; + } + + // Return access to sDoFRBMRCoeffs + inline const dictionary& coeffDict() const + { + return sDoFRBMRCoeffs_; + } }; From f8cad124c7309c2a6f128aa9d0a42912036de37f Mon Sep 17 00:00:00 2001 From: graham Date: Mon, 1 Feb 2010 16:58:34 +0000 Subject: [PATCH 11/14] ENC: sixDoFRigidBodyMotion. Adding fixedOrientation constraint. Adding report Switch to turn on reporting. Renaming linearSphericalAngularSpring to sphericalAngularSpring and getting a moment contribution from each axis. Can supply a reference orientation. --- .../functionObjects/forces/Make/files | 3 +- .../sixDoFRigidBodyMotion.C | 67 +++++-- .../sixDoFRigidBodyMotion.H | 39 +++- .../fixedOrientation/fixedOrientation.C | 180 ++++++++++++++++++ .../fixedOrientation/fixedOrientation.H | 126 ++++++++++++ .../fixedPoint/fixedPoint.C | 2 +- .../sixDoFRigidBodyMotionI.H | 32 ++-- .../sixDoFRigidBodyMotionIO.C | 2 + .../sphericalAngularSpring.C} | 76 ++++---- .../sphericalAngularSpring.H} | 27 +-- 10 files changed, 465 insertions(+), 89 deletions(-) create mode 100644 src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedOrientation/fixedOrientation.C create mode 100644 src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedOrientation/fixedOrientation.H rename src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/{linearSphericalAngularSpring/linearSphericalAngularSpring.C => sphericalAngularSpring/sphericalAngularSpring.C} (65%) rename src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/{linearSphericalAngularSpring/linearSphericalAngularSpring.H => sphericalAngularSpring/sphericalAngularSpring.H} (82%) diff --git a/src/postProcessing/functionObjects/forces/Make/files b/src/postProcessing/functionObjects/forces/Make/files index f0304ea6f0..d25c3977b1 100644 --- a/src/postProcessing/functionObjects/forces/Make/files +++ b/src/postProcessing/functionObjects/forces/Make/files @@ -16,7 +16,7 @@ sDoFRBMR = $(sDoFRBM)/sixDoFRigidBodyMotionRestraint $(sDoFRBMR)/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.C $(sDoFRBMR)/sixDoFRigidBodyMotionRestraint/newSixDoFRigidBodyMotionRestraint.C $(sDoFRBMR)/linearSpring/linearSpring.C -$(sDoFRBMR)/linearSphericalAngularSpring/linearSphericalAngularSpring.C +$(sDoFRBMR)/sphericalAngularSpring/sphericalAngularSpring.C sDoFRBMC = $(sDoFRBM)/sixDoFRigidBodyMotionConstraint @@ -25,6 +25,7 @@ $(sDoFRBMC)/sixDoFRigidBodyMotionConstraint/newSixDoFRigidBodyMotionConstraint.C $(sDoFRBMC)/fixedPoint/fixedPoint.C $(sDoFRBMC)/fixedPlane/fixedPlane.C $(sDoFRBMC)/fixedLine/fixedLine.C +$(sDoFRBMC)/fixedOrientation/fixedOrientation.C pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyDisplacementPointPatchVectorField.C pointPatchFields/derived/uncoupledSixDoFRigidBodyDisplacement/uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField.C diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C index d2c414b055..689a743cc9 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C @@ -45,9 +45,12 @@ void Foam::sixDoFRigidBodyMotion::applyRestraints() restraints_[rI].restrain(*this, rP, rF, rM); - // Info<< "Restraint " << rI << " force " << rF << nl - // << "Restraint " << rI << " moment " << rM - // << endl; + if (report_) + { + Info<< "Restraint " << restraints_[rI].name() << ": " + << "force " << rF << " moment " << rM + << endl; + } a() += rF/mass_; @@ -121,16 +124,16 @@ void Foam::sixDoFRigidBodyMotion::applyConstraints(scalar deltaT) << "iterations (" << maxConstraintIters_ << ") exceeded." << nl << exit(FatalError); } - else + else if (report_) { Info<< "sixDoFRigidBodyMotion constraints converged in " << iter << " iterations" - // << nl << "Constraint force: " << cFA << nl - // << "Constraint moment: " << cMA + << nl << "Constraint force: " << cFA << nl + << "Constraint moment: " << cMA << endl; } - // Add the constrain forces and moments to the motion state variables + // Add the constraint forces and moments to the motion state variables a() += cFA/mass_; // The moment of constraint forces has already been added @@ -150,7 +153,8 @@ Foam::sixDoFRigidBodyMotion::sixDoFRigidBodyMotion() maxConstraintIters_(0), refCentreOfMass_(vector::zero), momentOfInertia_(diagTensor::one*VSMALL), - mass_(VSMALL) + mass_(VSMALL), + report_(false) {} @@ -164,7 +168,8 @@ Foam::sixDoFRigidBodyMotion::sixDoFRigidBodyMotion const vector& tau, scalar mass, const point& refCentreOfMass, - const diagTensor& momentOfInertia + const diagTensor& momentOfInertia, + bool report ) : motionState_ @@ -181,7 +186,8 @@ Foam::sixDoFRigidBodyMotion::sixDoFRigidBodyMotion maxConstraintIters_(0), refCentreOfMass_(refCentreOfMass), momentOfInertia_(momentOfInertia), - mass_(mass) + mass_(mass), + report_(report) {} @@ -193,7 +199,8 @@ Foam::sixDoFRigidBodyMotion::sixDoFRigidBodyMotion(const dictionary& dict) maxConstraintIters_(0), refCentreOfMass_(dict.lookupOrDefault("refCentreOfMass", centreOfMass())), momentOfInertia_(dict.lookup("momentOfInertia")), - mass_(readScalar(dict.lookup("mass"))) + mass_(readScalar(dict.lookup("mass"))), + report_(dict.lookupOrDefault("report", false)) { addRestraints(dict); @@ -212,7 +219,8 @@ Foam::sixDoFRigidBodyMotion::sixDoFRigidBodyMotion maxConstraintIters_(sDoFRBM.maxConstraintIters()), refCentreOfMass_(sDoFRBM.refCentreOfMass()), momentOfInertia_(sDoFRBM.momentOfInertia()), - mass_(sDoFRBM.mass()) + mass_(sDoFRBM.mass()), + report_(sDoFRBM.report()) {} @@ -347,6 +355,11 @@ void Foam::sixDoFRigidBodyMotion::updateForce v() += 0.5*deltaT*a(); pi() += 0.5*deltaT*tau(); + + if(report_) + { + status(); + } } Pstream::scatter(motionState_); @@ -383,8 +396,8 @@ void Foam::sixDoFRigidBodyMotion::updateForce Foam::point Foam::sixDoFRigidBodyMotion::predictedPosition ( const point& pt, - const vector deltaForce, - const vector deltaMoment, + const vector& deltaForce, + const vector& deltaMoment, scalar deltaT ) const { @@ -402,4 +415,30 @@ Foam::point Foam::sixDoFRigidBodyMotion::predictedPosition } +Foam::vector Foam::sixDoFRigidBodyMotion::predictedOrientation +( + const vector& v, + const vector& deltaMoment, + scalar deltaT +) const +{ + vector piTemp = pi() + deltaT*(tau() + (Q().T() & deltaMoment)); + + tensor QTemp = Q(); + + rotate(QTemp, piTemp, deltaT); + + return (QTemp & v); +} + + +void Foam::sixDoFRigidBodyMotion::status() const +{ + Info<< "Centre of mass: " << centreOfMass() << nl + << "Linear velocity: " << v() << nl + << "Angular velocity: " << omega() + << endl; +} + + // ************************************************************************* // diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.H index 343403eb0a..348e5ddf8d 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.H +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.H @@ -107,6 +107,9 @@ class sixDoFRigidBodyMotion //- Mass of the body scalar mass_; + //- Switch to turn reporting of motion data on and off + Switch report_; + // Private Member Functions @@ -154,9 +157,6 @@ class sixDoFRigidBodyMotion //- Return access to the centre of mass inline const point& refCentreOfMass() const; - //- Return access to the inertia tensor - inline const diagTensor& momentOfInertia() const; - //- Return access to the orientation inline const tensor& Q() const; @@ -178,9 +178,6 @@ class sixDoFRigidBodyMotion //- Return access to the centre of mass inline point& refCentreOfMass(); - //- Return non-const access to the inertia tensor - inline diagTensor& momentOfInertia(); - //- Return non-const access to the orientation inline tensor& Q(); @@ -215,7 +212,8 @@ public: const vector& tau, scalar mass, const point& refCentreOfMass, - const diagTensor& momentOfInertia + const diagTensor& momentOfInertia, + bool report = false ); //- Construct from dictionary @@ -282,8 +280,18 @@ public: point predictedPosition ( const point& pt, - const vector deltaForce, - const vector deltaMoment, + const vector& deltaForce, + const vector& deltaMoment, + scalar deltaT + ) const; + + //- Predict the orientation of the supplied vector after deltaT + // given the current motion state and the additional supplied + // moment + vector predictedOrientation + ( + const vector& v, + const vector& deltaMoment, scalar deltaT ) const; @@ -294,20 +302,33 @@ public: // motion state inline point currentVelocity(const point& pt) const; + //- Report the status of the motion + void status() const; + + // Access //- Return const access to the centre of mass inline const point& centreOfMass() const; + //- Return access to the inertia tensor + inline const diagTensor& momentOfInertia() const; + //- Return const access to the mass inline scalar mass() const; + //- Return the report Switch + inline bool report() const; + // Edit //- Return non-const access to the centre of mass inline point& centreOfMass(); + //- Return non-const access to the inertia tensor + inline diagTensor& momentOfInertia(); + //- Return non-const access to the mass inline scalar& mass(); diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedOrientation/fixedOrientation.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedOrientation/fixedOrientation.C new file mode 100644 index 0000000000..da4b949831 --- /dev/null +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedOrientation/fixedOrientation.C @@ -0,0 +1,180 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-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 + +\*---------------------------------------------------------------------------*/ + +#include "fixedOrientation.H" +#include "addToRunTimeSelectionTable.H" +#include "sixDoFRigidBodyMotion.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace sixDoFRigidBodyMotionConstraints +{ + defineTypeNameAndDebug(fixedOrientation, 0); + addToRunTimeSelectionTable + ( + sixDoFRigidBodyMotionConstraint, + fixedOrientation, + dictionary + ); +}; +}; + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::sixDoFRigidBodyMotionConstraints::fixedOrientation::fixedOrientation +( + const dictionary& sDoFRBMCDict +) +: + sixDoFRigidBodyMotionConstraint(sDoFRBMCDict), + fixedOrientation_() +{ + read(sDoFRBMCDict); +} + + +// * * * * * * * * * * * * * * * * Destructors * * * * * * * * * * * * * * * // + +Foam::sixDoFRigidBodyMotionConstraints::fixedOrientation::~fixedOrientation() +{} + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +bool Foam::sixDoFRigidBodyMotionConstraints::fixedOrientation::constrain +( + const sixDoFRigidBodyMotion& motion, + const vector& existingConstraintForce, + const vector& existingConstraintMoment, + scalar deltaT, + vector& constraintPosition, + vector& constraintForceIncrement, + vector& constraintMomentIncrement +) const +{ + constraintMomentIncrement = vector::zero; + + scalar maxTheta = -SMALL; + + for (direction cmpt=0; cmpt VSMALL) + { + predictedDir /= magPredictedDir; + + theta = acos(predictedDir & refDir); + + // Recalculating axis to give correct sign to angle + axis = (refDir ^ predictedDir); + + scalar magAxis = mag(axis); + + if (magAxis > VSMALL) + { + axis /= magAxis; + } + else + { + axis = vector::zero; + } + } + + if (theta > maxTheta) + { + maxTheta = theta; + } + + constraintMomentIncrement += + -relaxationFactor_ + *theta*axis + *motion.momentOfInertia()[cmpt]/sqr(deltaT); + } + + constraintPosition = motion.centreOfMass(); + + constraintForceIncrement = vector::zero; + + return (mag(maxTheta) < tolerance_); +} + + +bool Foam::sixDoFRigidBodyMotionConstraints::fixedOrientation::read +( + const dictionary& sDoFRBMCDict +) +{ + sixDoFRigidBodyMotionConstraint::read(sDoFRBMCDict); + + fixedOrientation_ = + sDoFRBMCCoeffs_.lookupOrDefault("fixedOrientation", I); + + if (mag(mag(fixedOrientation_) - sqrt(3.0)) > 1e-9) + { + FatalErrorIn + ( + "Foam::sixDoFRigidBodyMotionConstraints::fixedOrientation::read" + "(" + "const dictionary& sDoFRBMCDict" + ")" + ) + << "fixedOrientation " << fixedOrientation_ + << " is not a rotation tensor." + << exit(FatalError); + } + + return true; +} + +// ************************************************************************* // diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedOrientation/fixedOrientation.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedOrientation/fixedOrientation.H new file mode 100644 index 0000000000..5f6af014cc --- /dev/null +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedOrientation/fixedOrientation.H @@ -0,0 +1,126 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-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 + Foam::sixDoFRigidBodyMotionConstraints::fixedOrientation + +Description + sixDoFRigidBodyMotionConstraint. Orientation of body fixed global + space. Only valid where the predicted deviation from alignment is + < 90 degrees. + +SourceFiles + fixedOrientation.C + +\*---------------------------------------------------------------------------*/ + +#ifndef fixedOrientation_H +#define fixedOrientation_H + +#include "sixDoFRigidBodyMotionConstraint.H" +#include "point.H" +#include "tensor.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +namespace sixDoFRigidBodyMotionConstraints +{ + +/*---------------------------------------------------------------------------*\ + Class fixedOrientation Declaration +\*---------------------------------------------------------------------------*/ + +class fixedOrientation +: + public sixDoFRigidBodyMotionConstraint +{ + + // Private data + + //- Reference orientation where there is no moment + tensor fixedOrientation_; + +public: + + //- Runtime type information + TypeName("fixedOrientation"); + + + // Constructors + + //- Construct from components + fixedOrientation + ( + const dictionary& sDoFRBMCDict + ); + + //- Construct and return a clone + virtual autoPtr clone() const + { + return autoPtr + ( + new fixedOrientation(*this) + ); + } + + + // Destructor + + virtual ~fixedOrientation(); + + + // Member Functions + + //- Calculate the constraint position, force and moment. + // Global reference frame vectors. Returns boolean stating + // whether the constraint been converged to tolerance. + virtual bool constrain + ( + const sixDoFRigidBodyMotion& motion, + const vector& existingConstraintForce, + const vector& existingConstraintMoment, + scalar deltaT, + vector& constraintPosition, + vector& constraintForceIncrement, + vector& constraintMomentIncrement + ) const; + + //- Update properties from given dictionary + virtual bool read(const dictionary& sDoFRBMCCoeff); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace solidBodyMotionFunctions +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPoint/fixedPoint.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPoint/fixedPoint.C index 3862f16e65..cfe8b5421d 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPoint/fixedPoint.C +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedPoint/fixedPoint.C @@ -53,7 +53,7 @@ Foam::sixDoFRigidBodyMotionConstraints::fixedPoint::fixedPoint ) : sixDoFRigidBodyMotionConstraint(sDoFRBMCDict), - fixedPoint_(sDoFRBMCCoeffs_.lookup("fixedPoint")) + fixedPoint_() { read(sDoFRBMCDict); } diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionI.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionI.H index 18607cc86f..7de803afe1 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionI.H +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionI.H @@ -126,13 +126,6 @@ inline const Foam::point& Foam::sixDoFRigidBodyMotion::refCentreOfMass() const } -inline const Foam::diagTensor& -Foam::sixDoFRigidBodyMotion::momentOfInertia() const -{ - return momentOfInertia_; -} - - inline const Foam::tensor& Foam::sixDoFRigidBodyMotion::Q() const { return motionState_.Q(); @@ -169,12 +162,6 @@ inline Foam::point& Foam::sixDoFRigidBodyMotion::refCentreOfMass() } -inline Foam::diagTensor& Foam::sixDoFRigidBodyMotion::momentOfInertia() -{ - return momentOfInertia_; -} - - inline Foam::tensor& Foam::sixDoFRigidBodyMotion::Q() { return motionState_.Q(); @@ -253,18 +240,37 @@ inline const Foam::point& Foam::sixDoFRigidBodyMotion::centreOfMass() const } +inline const Foam::diagTensor& +Foam::sixDoFRigidBodyMotion::momentOfInertia() const +{ + return momentOfInertia_; +} + + inline Foam::scalar Foam::sixDoFRigidBodyMotion::mass() const { return mass_; } +inline bool Foam::sixDoFRigidBodyMotion::report() const +{ + return report_; +} + + inline Foam::point& Foam::sixDoFRigidBodyMotion::centreOfMass() { return motionState_.centreOfMass(); } +inline Foam::diagTensor& Foam::sixDoFRigidBodyMotion::momentOfInertia() +{ + return momentOfInertia_; +} + + inline Foam::scalar& Foam::sixDoFRigidBodyMotion::mass() { return mass_; diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionIO.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionIO.C index e8172f4183..55245c3bfe 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionIO.C +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionIO.C @@ -39,6 +39,8 @@ void Foam::sixDoFRigidBodyMotion::write(Ostream& os) const << momentOfInertia_ << token::END_STATEMENT << nl; os.writeKeyword("mass") << mass_ << token::END_STATEMENT << nl; + os.writeKeyword("report") + << report_ << token::END_STATEMENT << nl; if (restraints_.size()) { diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSphericalAngularSpring/linearSphericalAngularSpring.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sphericalAngularSpring/sphericalAngularSpring.C similarity index 65% rename from src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSphericalAngularSpring/linearSphericalAngularSpring.C rename to src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sphericalAngularSpring/sphericalAngularSpring.C index 2672d2d26e..8b47cd4ca6 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSphericalAngularSpring/linearSphericalAngularSpring.C +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sphericalAngularSpring/sphericalAngularSpring.C @@ -24,7 +24,7 @@ License \*---------------------------------------------------------------------------*/ -#include "linearSphericalAngularSpring.H" +#include "sphericalAngularSpring.H" #include "addToRunTimeSelectionTable.H" #include "sixDoFRigidBodyMotion.H" @@ -34,11 +34,11 @@ namespace Foam { namespace sixDoFRigidBodyMotionRestraints { - defineTypeNameAndDebug(linearSphericalAngularSpring, 0); + defineTypeNameAndDebug(sphericalAngularSpring, 0); addToRunTimeSelectionTable ( sixDoFRigidBodyMotionRestraint, - linearSphericalAngularSpring, + sphericalAngularSpring, dictionary ); }; @@ -47,14 +47,14 @@ namespace sixDoFRigidBodyMotionRestraints // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // -Foam::sixDoFRigidBodyMotionRestraints::linearSphericalAngularSpring:: -linearSphericalAngularSpring +Foam::sixDoFRigidBodyMotionRestraints::sphericalAngularSpring:: +sphericalAngularSpring ( const dictionary& sDoFRBMRDict ) : sixDoFRigidBodyMotionRestraint(sDoFRBMRDict), - refDir_(), + refQ_(), stiffness_(), damping_() { @@ -64,15 +64,15 @@ linearSphericalAngularSpring // * * * * * * * * * * * * * * * * Destructors * * * * * * * * * * * * * * * // -Foam::sixDoFRigidBodyMotionRestraints::linearSphericalAngularSpring:: -~linearSphericalAngularSpring() +Foam::sixDoFRigidBodyMotionRestraints::sphericalAngularSpring:: +~sphericalAngularSpring() {} // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // void -Foam::sixDoFRigidBodyMotionRestraints::linearSphericalAngularSpring::restrain +Foam::sixDoFRigidBodyMotionRestraints::sphericalAngularSpring::restrain ( const sixDoFRigidBodyMotion& motion, vector& restraintPosition, @@ -80,62 +80,62 @@ Foam::sixDoFRigidBodyMotionRestraints::linearSphericalAngularSpring::restrain vector& restraintMoment ) const { - vector curDir = motion.currentOrientation(refDir_); + restraintMoment = vector::zero; - vector a = refDir_ ^ curDir; - - scalar magA = mag(a); - - scalar theta = 0; - - if (magA > VSMALL) + for (direction cmpt=0; cmpt> refDir_; + refQ_ = sDoFRBMRCoeffs_.lookupOrDefault("referenceOrientation", I); - scalar magRefDir(mag(refDir_)); - - if (magRefDir > VSMALL) - { - refDir_ /= magRefDir; - } - else + if (mag(mag(refQ_) - sqrt(3.0)) > 1e-9) { FatalErrorIn ( - "bool Foam::sixDoFRigidBodyMotionRestraints::" - "linearSphericalAngularSpring ::read" + "Foam::sixDoFRigidBodyMotionConstraints::sphericalAngularSpring::" + "read" "(" "const dictionary& sDoFRBMRDict" ")" ) - << "referenceDirection has zero length" - << abort(FatalError); + << "referenceOrientation " << refQ_ << " is not a rotation tensor. " + << "mag(referenceOrientation) - sqrt(3) = " + << mag(refQ_) - sqrt(3.0) << nl + << exit(FatalError); } sDoFRBMRCoeffs_.lookup("stiffness") >> stiffness_; diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSphericalAngularSpring/linearSphericalAngularSpring.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sphericalAngularSpring/sphericalAngularSpring.H similarity index 82% rename from src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSphericalAngularSpring/linearSphericalAngularSpring.H rename to src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sphericalAngularSpring/sphericalAngularSpring.H index d43b264cf9..6ee6636b29 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearSphericalAngularSpring/linearSphericalAngularSpring.H +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sphericalAngularSpring/sphericalAngularSpring.H @@ -23,21 +23,22 @@ License Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Class - Foam::sixDoFRigidBodyMotionRestraints::linearSphericalAngularSpring + Foam::sixDoFRigidBodyMotionRestraints::sphericalAngularSpring Description - sixDoFRigidBodyMotionRestraints model. Linear spherical angular spring. + sixDoFRigidBodyMotionRestraints model. Spherical angular spring. SourceFiles - linearSphericalAngularSpring.C + sphericalAngularSpring.C \*---------------------------------------------------------------------------*/ -#ifndef linearSphericalAngularSpring_H -#define linearSphericalAngularSpring_H +#ifndef sphericalAngularSpring_H +#define sphericalAngularSpring_H #include "sixDoFRigidBodyMotionRestraint.H" #include "point.H" +#include "tensor.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -48,17 +49,17 @@ namespace sixDoFRigidBodyMotionRestraints { /*---------------------------------------------------------------------------*\ - Class linearSphericalAngularSpring Declaration + Class sphericalAngularSpring Declaration \*---------------------------------------------------------------------------*/ -class linearSphericalAngularSpring +class sphericalAngularSpring : public sixDoFRigidBodyMotionRestraint { // Private data - // Reference direction there is no spring reaction torque - vector refDir_; + //- Reference orientation where there is no moment + tensor refQ_; //- Spring stiffness coefficient (Nm/rad) scalar stiffness_; @@ -70,13 +71,13 @@ class linearSphericalAngularSpring public: //- Runtime type information - TypeName("linearSphericalAngularSpring"); + TypeName("sphericalAngularSpring"); // Constructors //- Construct from components - linearSphericalAngularSpring + sphericalAngularSpring ( const dictionary& sDoFRBMRDict ); @@ -86,14 +87,14 @@ public: { return autoPtr ( - new linearSphericalAngularSpring(*this) + new sphericalAngularSpring(*this) ); } // Destructor - virtual ~linearSphericalAngularSpring(); + virtual ~sphericalAngularSpring(); // Member Functions From f26b41ef0cb8aefcd156b0309e2673303bb6de90 Mon Sep 17 00:00:00 2001 From: graham Date: Mon, 1 Feb 2010 19:59:15 +0000 Subject: [PATCH 12/14] ENC: sixDoFRigidBodyMotion. Adding linearAxialAngularSpring restraint. --- .../functionObjects/forces/Make/files | 1 + .../fixedOrientation/fixedOrientation.C | 2 +- .../fixedOrientation/fixedOrientation.H | 1 + .../linearAxialAngularSpring.C | 193 ++++++++++++++++++ .../linearAxialAngularSpring.H | 129 ++++++++++++ .../sphericalAngularSpring.C | 2 +- 6 files changed, 326 insertions(+), 2 deletions(-) create mode 100644 src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearAxialAngularSpring/linearAxialAngularSpring.C create mode 100644 src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearAxialAngularSpring/linearAxialAngularSpring.H diff --git a/src/postProcessing/functionObjects/forces/Make/files b/src/postProcessing/functionObjects/forces/Make/files index d25c3977b1..4bf07db958 100644 --- a/src/postProcessing/functionObjects/forces/Make/files +++ b/src/postProcessing/functionObjects/forces/Make/files @@ -17,6 +17,7 @@ $(sDoFRBMR)/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.C $(sDoFRBMR)/sixDoFRigidBodyMotionRestraint/newSixDoFRigidBodyMotionRestraint.C $(sDoFRBMR)/linearSpring/linearSpring.C $(sDoFRBMR)/sphericalAngularSpring/sphericalAngularSpring.C +$(sDoFRBMR)/linearAxialAngularSpring/linearAxialAngularSpring.C sDoFRBMC = $(sDoFRBM)/sixDoFRigidBodyMotionConstraint diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedOrientation/fixedOrientation.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedOrientation/fixedOrientation.C index da4b949831..03ba862b71 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedOrientation/fixedOrientation.C +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedOrientation/fixedOrientation.C @@ -139,7 +139,7 @@ bool Foam::sixDoFRigidBodyMotionConstraints::fixedOrientation::constrain constraintMomentIncrement += -relaxationFactor_ *theta*axis - *motion.momentOfInertia()[cmpt]/sqr(deltaT); + *motion.momentOfInertia()[cmpt]/sqr(deltaT); } constraintPosition = motion.centreOfMass(); diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedOrientation/fixedOrientation.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedOrientation/fixedOrientation.H index 5f6af014cc..0d46cddea9 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedOrientation/fixedOrientation.H +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedOrientation/fixedOrientation.H @@ -64,6 +64,7 @@ class fixedOrientation //- Reference orientation where there is no moment tensor fixedOrientation_; + public: //- Runtime type information diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearAxialAngularSpring/linearAxialAngularSpring.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearAxialAngularSpring/linearAxialAngularSpring.C new file mode 100644 index 0000000000..bed025bae6 --- /dev/null +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearAxialAngularSpring/linearAxialAngularSpring.C @@ -0,0 +1,193 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-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 + +\*---------------------------------------------------------------------------*/ + +#include "linearAxialAngularSpring.H" +#include "addToRunTimeSelectionTable.H" +#include "sixDoFRigidBodyMotion.H" +#include "transform.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace sixDoFRigidBodyMotionRestraints +{ + defineTypeNameAndDebug(linearAxialAngularSpring, 0); + addToRunTimeSelectionTable + ( + sixDoFRigidBodyMotionRestraint, + linearAxialAngularSpring, + dictionary + ); +}; +}; + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::sixDoFRigidBodyMotionRestraints::linearAxialAngularSpring:: +linearAxialAngularSpring +( + const dictionary& sDoFRBMRDict +) +: + sixDoFRigidBodyMotionRestraint(sDoFRBMRDict), + refQ_(), + axis_(), + stiffness_(), + damping_() +{ + read(sDoFRBMRDict); +} + + +// * * * * * * * * * * * * * * * * Destructors * * * * * * * * * * * * * * * // + +Foam::sixDoFRigidBodyMotionRestraints::linearAxialAngularSpring:: +~linearAxialAngularSpring() +{} + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +void +Foam::sixDoFRigidBodyMotionRestraints::linearAxialAngularSpring::restrain +( + const sixDoFRigidBodyMotion& motion, + vector& restraintPosition, + vector& restraintForce, + vector& restraintMoment +) const +{ + vector refDir = rotationTensor(vector(1, 0 ,0), axis_) & vector(0, 1, 0); + + vector oldDir = refQ_ & refDir; + + vector newDir = motion.currentOrientation(refDir); + + if (mag(oldDir & axis_) > 0.95 || mag(newDir & axis_) > 0.95) + { + // Directions getting close to the axis, change reference + + refDir = rotationTensor(vector(1, 0 ,0), axis_) & vector(0, 0, 1); + + vector oldDir = refQ_ & refDir; + + vector newDir = motion.currentOrientation(refDir); + } + + // Removing any axis component from oldDir and newDir and normalising + oldDir -= (axis_ & oldDir)*axis_; + oldDir /= mag(oldDir); + + newDir -= (axis_ & newDir)*axis_; + newDir /= mag(newDir); + + scalar theta = mag(acos(oldDir & newDir)); + + // Temporary axis with sign information. + vector a = (oldDir ^ newDir); + + // Remove any component that is not along axis that may creep in + a = (a & axis_)*axis_; + + scalar magA = mag(a); + + if (magA > VSMALL) + { + a /= magA; + } + else + { + a = vector::zero; + } + + // Damping of along axis angular velocity only + restraintMoment = -stiffness_*theta*a - damping_*(motion.omega() & a)*a; + + restraintForce = vector::zero; + + // Not needed to be altered as restraintForce is zero, but set to + // centreOfMass to be sure of no spurious moment + restraintPosition = motion.centreOfMass(); +} + + +bool Foam::sixDoFRigidBodyMotionRestraints::linearAxialAngularSpring::read +( + const dictionary& sDoFRBMRDict +) +{ + sixDoFRigidBodyMotionRestraint::read(sDoFRBMRDict); + + refQ_ = sDoFRBMRCoeffs_.lookupOrDefault("referenceOrientation", I); + + if (mag(mag(refQ_) - sqrt(3.0)) > 1e-9) + { + FatalErrorIn + ( + "Foam::sixDoFRigidBodyMotionRestraints::linearAxialAngularSpring::" + "read" + "(" + "const dictionary& sDoFRBMRDict" + ")" + ) + << "referenceOrientation " << refQ_ << " is not a rotation tensor. " + << "mag(referenceOrientation) - sqrt(3) = " + << mag(refQ_) - sqrt(3.0) << nl + << exit(FatalError); + } + + axis_ = sDoFRBMRCoeffs_.lookup("axis"); + + scalar magAxis(mag(axis_)); + + if (magAxis > VSMALL) + { + axis_ /= magAxis; + } + else + { + FatalErrorIn + ( + "Foam::sixDoFRigidBodyMotionRestraints::linearAxialAngularSpring::" + "read" + "(" + "const dictionary& sDoFRBMCDict" + ")" + ) + << "axis has zero length" + << abort(FatalError); + } + + sDoFRBMRCoeffs_.lookup("stiffness") >> stiffness_; + + sDoFRBMRCoeffs_.lookup("damping") >> damping_; + + return true; +} + +// ************************************************************************* // diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearAxialAngularSpring/linearAxialAngularSpring.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearAxialAngularSpring/linearAxialAngularSpring.H new file mode 100644 index 0000000000..780598afb2 --- /dev/null +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/linearAxialAngularSpring/linearAxialAngularSpring.H @@ -0,0 +1,129 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-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 + Foam::sixDoFRigidBodyMotionRestraints::linearAxialAngularSpring + +Description + sixDoFRigidBodyMotionRestraints model. Linear axial angular spring. + +SourceFiles + linearAxialAngularSpring.C + +\*---------------------------------------------------------------------------*/ + +#ifndef linearAxialAngularSpring_H +#define linearAxialAngularSpring_H + +#include "sixDoFRigidBodyMotionRestraint.H" +#include "point.H" +#include "tensor.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +namespace sixDoFRigidBodyMotionRestraints +{ + +/*---------------------------------------------------------------------------*\ + Class linearAxialAngularSpring Declaration +\*---------------------------------------------------------------------------*/ + +class linearAxialAngularSpring +: + public sixDoFRigidBodyMotionRestraint +{ + // Private data + + //- Reference orientation where there is no moment + tensor refQ_; + + //- Global unit axis around which the motion is sprung + vector axis_; + + //- Spring stiffness coefficient (Nm/rad) + scalar stiffness_; + + //- Damping coefficient (Nms/rad) + scalar damping_; + + +public: + + //- Runtime type information + TypeName("linearAxialAngularSpring"); + + + // Constructors + + //- Construct from components + linearAxialAngularSpring + ( + const dictionary& sDoFRBMRDict + ); + + //- Construct and return a clone + virtual autoPtr clone() const + { + return autoPtr + ( + new linearAxialAngularSpring(*this) + ); + } + + + // Destructor + + virtual ~linearAxialAngularSpring(); + + + // Member Functions + + //- Calculate the restraint position, force and moment. + // Global reference frame vectors. + virtual void restrain + ( + const sixDoFRigidBodyMotion& motion, + vector& restraintPosition, + vector& restraintForce, + vector& restraintMoment + ) const; + + //- Update properties from given dictionary + virtual bool read(const dictionary& sDoFRBMRCoeff); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace solidBodyMotionFunctions +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sphericalAngularSpring/sphericalAngularSpring.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sphericalAngularSpring/sphericalAngularSpring.C index 8b47cd4ca6..af11dcb421 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sphericalAngularSpring/sphericalAngularSpring.C +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/sphericalAngularSpring/sphericalAngularSpring.C @@ -126,7 +126,7 @@ bool Foam::sixDoFRigidBodyMotionRestraints::sphericalAngularSpring::read { FatalErrorIn ( - "Foam::sixDoFRigidBodyMotionConstraints::sphericalAngularSpring::" + "Foam::sixDoFRigidBodyMotionRestraints::sphericalAngularSpring::" "read" "(" "const dictionary& sDoFRBMRDict" From 8e850800f7f106e847ed7cb6a1d3f40d151cb63a Mon Sep 17 00:00:00 2001 From: graham Date: Tue, 2 Feb 2010 11:51:52 +0000 Subject: [PATCH 13/14] ENC: sixDoFRigidBodyMotion. Adding fixedAxis constraint. --- .../functionObjects/forces/Make/files | 7 +- .../sixDoFRigidBodyMotion.C | 5 +- .../sixDoFRigidBodyMotion.H | 7 +- .../fixedAxis/fixedAxis.C | 157 ++++++++++++++++++ .../fixedAxis/fixedAxis.H | 126 ++++++++++++++ .../sixDoFRigidBodyMotionI.H | 9 +- 6 files changed, 305 insertions(+), 6 deletions(-) create mode 100644 src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedAxis/fixedAxis.C create mode 100644 src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedAxis/fixedAxis.H diff --git a/src/postProcessing/functionObjects/forces/Make/files b/src/postProcessing/functionObjects/forces/Make/files index 4bf07db958..59996bffc9 100644 --- a/src/postProcessing/functionObjects/forces/Make/files +++ b/src/postProcessing/functionObjects/forces/Make/files @@ -15,18 +15,19 @@ sDoFRBMR = $(sDoFRBM)/sixDoFRigidBodyMotionRestraint $(sDoFRBMR)/sixDoFRigidBodyMotionRestraint/sixDoFRigidBodyMotionRestraint.C $(sDoFRBMR)/sixDoFRigidBodyMotionRestraint/newSixDoFRigidBodyMotionRestraint.C +$(sDoFRBMR)/linearAxialAngularSpring/linearAxialAngularSpring.C $(sDoFRBMR)/linearSpring/linearSpring.C $(sDoFRBMR)/sphericalAngularSpring/sphericalAngularSpring.C -$(sDoFRBMR)/linearAxialAngularSpring/linearAxialAngularSpring.C sDoFRBMC = $(sDoFRBM)/sixDoFRigidBodyMotionConstraint $(sDoFRBMC)/sixDoFRigidBodyMotionConstraint/sixDoFRigidBodyMotionConstraint.C $(sDoFRBMC)/sixDoFRigidBodyMotionConstraint/newSixDoFRigidBodyMotionConstraint.C -$(sDoFRBMC)/fixedPoint/fixedPoint.C -$(sDoFRBMC)/fixedPlane/fixedPlane.C +$(sDoFRBMC)/fixedAxis/fixedAxis.C $(sDoFRBMC)/fixedLine/fixedLine.C $(sDoFRBMC)/fixedOrientation/fixedOrientation.C +$(sDoFRBMC)/fixedPlane/fixedPlane.C +$(sDoFRBMC)/fixedPoint/fixedPoint.C pointPatchFields/derived/sixDoFRigidBodyDisplacement/sixDoFRigidBodyDisplacementPointPatchVectorField.C pointPatchFields/derived/uncoupledSixDoFRigidBodyDisplacement/uncoupledSixDoFRigidBodyDisplacementPointPatchVectorField.C diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C index 689a743cc9..1088ab1506 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.C @@ -54,6 +54,8 @@ void Foam::sixDoFRigidBodyMotion::applyRestraints() a() += rF/mass_; + // Moments are returned in global axes, transforming to + // body local to add to torque. tau() += Q().T() & (rM + ((rP - centreOfMass()) ^ rF)); } } @@ -137,7 +139,8 @@ void Foam::sixDoFRigidBodyMotion::applyConstraints(scalar deltaT) a() += cFA/mass_; // The moment of constraint forces has already been added - // during accumulation + // during accumulation. Moments are returned in global axes, + // transforming to body local tau() += Q().T() & cMA; } } diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.H index 348e5ddf8d..ecde4ac6d7 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.H +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion.H @@ -272,7 +272,12 @@ public: //- Transform the given reference state direction by the current // motion state - inline point currentOrientation(const vector& refDir) const; + inline vector currentOrientation(const vector& refDir) const; + + //- Access the orientation tensor, Q. + // globalVector = Q & bodyLocalVector + // bodyLocalVector = Q.T() & globalVector + inline const tensor& currentOrientation() const; //- Predict the position of the supplied point after deltaT // given the current motion state and the additional supplied diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedAxis/fixedAxis.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedAxis/fixedAxis.C new file mode 100644 index 0000000000..996b76b06c --- /dev/null +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedAxis/fixedAxis.C @@ -0,0 +1,157 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-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 + +\*---------------------------------------------------------------------------*/ + +#include "fixedAxis.H" +#include "addToRunTimeSelectionTable.H" +#include "sixDoFRigidBodyMotion.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace sixDoFRigidBodyMotionConstraints +{ + defineTypeNameAndDebug(fixedAxis, 0); + addToRunTimeSelectionTable + ( + sixDoFRigidBodyMotionConstraint, + fixedAxis, + dictionary + ); +}; +}; + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::sixDoFRigidBodyMotionConstraints::fixedAxis::fixedAxis +( + const dictionary& sDoFRBMCDict +) +: + sixDoFRigidBodyMotionConstraint(sDoFRBMCDict), + fixedAxis_() +{ + read(sDoFRBMCDict); +} + + +// * * * * * * * * * * * * * * * * Destructors * * * * * * * * * * * * * * * // + +Foam::sixDoFRigidBodyMotionConstraints::fixedAxis::~fixedAxis() +{} + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +bool Foam::sixDoFRigidBodyMotionConstraints::fixedAxis::constrain +( + const sixDoFRigidBodyMotion& motion, + const vector& existingConstraintForce, + const vector& existingConstraintMoment, + scalar deltaT, + vector& constraintPosition, + vector& constraintForceIncrement, + vector& constraintMomentIncrement +) const +{ + constraintMomentIncrement = vector::zero; + + vector predictedDir = motion.predictedOrientation + ( + fixedAxis_, + existingConstraintMoment, + deltaT + ); + + scalar theta = acos(predictedDir & fixedAxis_); + + vector rotationAxis = fixedAxis_ ^ predictedDir; + + scalar magRotationAxis = mag(rotationAxis); + + if (magRotationAxis > VSMALL) + { + rotationAxis /= magRotationAxis; + + const tensor& Q = motion.currentOrientation(); + + // Transform rotationAxis to body local system + rotationAxis = Q.T() & rotationAxis; + + constraintMomentIncrement = + -relaxationFactor_ + *(motion.momentOfInertia() & rotationAxis) + *theta/sqr(deltaT); + + // Transform moment increment to global system + constraintMomentIncrement = Q & constraintMomentIncrement; + + // Remove any moment that is around the fixedAxis_ + constraintMomentIncrement -= + (constraintMomentIncrement & fixedAxis_)*fixedAxis_; + } + + constraintPosition = motion.centreOfMass(); + + constraintForceIncrement = vector::zero; + + return (mag(theta) < tolerance_); +} + + +bool Foam::sixDoFRigidBodyMotionConstraints::fixedAxis::read +( + const dictionary& sDoFRBMCDict +) +{ + sixDoFRigidBodyMotionConstraint::read(sDoFRBMCDict); + + sDoFRBMCCoeffs_.lookup("axis") >> fixedAxis_; + + scalar magFixedAxis(mag(fixedAxis_)); + + if (magFixedAxis > VSMALL) + { + fixedAxis_ /= magFixedAxis; + } + else + { + FatalErrorIn + ( + "Foam::sixDoFRigidBodyMotionConstraints::fixedAxis::read" + "(" + "const dictionary& sDoFRBMCDict" + ")" + ) + << "axis has zero length" + << abort(FatalError); + } + + return true; +} + +// ************************************************************************* // diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedAxis/fixedAxis.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedAxis/fixedAxis.H new file mode 100644 index 0000000000..5ba3dcb60d --- /dev/null +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionConstraint/fixedAxis/fixedAxis.H @@ -0,0 +1,126 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-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 + Foam::sixDoFRigidBodyMotionConstraints::fixedAxis + +Description + sixDoFRigidBodyMotionConstraint. Axis of body fixed global + space. + +SourceFiles + fixedAxis.C + +\*---------------------------------------------------------------------------*/ + +#ifndef fixedAxis_H +#define fixedAxis_H + +#include "sixDoFRigidBodyMotionConstraint.H" +#include "point.H" +#include "tensor.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +namespace sixDoFRigidBodyMotionConstraints +{ + +/*---------------------------------------------------------------------------*\ + Class fixedAxis Declaration +\*---------------------------------------------------------------------------*/ + +class fixedAxis +: + public sixDoFRigidBodyMotionConstraint +{ + + // Private data + + //- Reference axis in global space + vector fixedAxis_; + + +public: + + //- Runtime type information + TypeName("fixedAxis"); + + + // Constructors + + //- Construct from components + fixedAxis + ( + const dictionary& sDoFRBMCDict + ); + + //- Construct and return a clone + virtual autoPtr clone() const + { + return autoPtr + ( + new fixedAxis(*this) + ); + } + + + // Destructor + + virtual ~fixedAxis(); + + + // Member Functions + + //- Calculate the constraint position, force and moment. + // Global reference frame vectors. Returns boolean stating + // whether the constraint been converged to tolerance. + virtual bool constrain + ( + const sixDoFRigidBodyMotion& motion, + const vector& existingConstraintForce, + const vector& existingConstraintMoment, + scalar deltaT, + vector& constraintPosition, + vector& constraintForceIncrement, + vector& constraintMomentIncrement + ) const; + + //- Update properties from given dictionary + virtual bool read(const dictionary& sDoFRBMCCoeff); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace solidBodyMotionFunctions +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionI.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionI.H index 7de803afe1..f112ef42ef 100644 --- a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionI.H +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionI.H @@ -210,7 +210,7 @@ inline Foam::point Foam::sixDoFRigidBodyMotion::currentPosition } -inline Foam::point Foam::sixDoFRigidBodyMotion::currentOrientation +inline Foam::vector Foam::sixDoFRigidBodyMotion::currentOrientation ( const vector& refDir ) const @@ -219,6 +219,13 @@ inline Foam::point Foam::sixDoFRigidBodyMotion::currentOrientation } +inline const Foam::tensor& +Foam::sixDoFRigidBodyMotion::currentOrientation() const +{ + return Q(); +} + + inline Foam::vector Foam::sixDoFRigidBodyMotion::omega() const { return Q() & (inv(momentOfInertia_) & pi()); From 58052e72f87a238b4ed441d55e0479af7b970bea Mon Sep 17 00:00:00 2001 From: graham Date: Tue, 2 Feb 2010 13:17:17 +0000 Subject: [PATCH 14/14] ENC: sixDoFRigidBodyMotion. Adding tabulatedAxialAngularSpring restraint. --- .../functionObjects/forces/Make/files | 1 + .../tabulatedAxialAngularSpring.C | 230 ++++++++++++++++++ .../tabulatedAxialAngularSpring.H | 137 +++++++++++ 3 files changed, 368 insertions(+) create mode 100644 src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/tabulatedAxialAngularSpring/tabulatedAxialAngularSpring.C create mode 100644 src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/tabulatedAxialAngularSpring/tabulatedAxialAngularSpring.H diff --git a/src/postProcessing/functionObjects/forces/Make/files b/src/postProcessing/functionObjects/forces/Make/files index 59996bffc9..6538e133ef 100644 --- a/src/postProcessing/functionObjects/forces/Make/files +++ b/src/postProcessing/functionObjects/forces/Make/files @@ -18,6 +18,7 @@ $(sDoFRBMR)/sixDoFRigidBodyMotionRestraint/newSixDoFRigidBodyMotionRestraint.C $(sDoFRBMR)/linearAxialAngularSpring/linearAxialAngularSpring.C $(sDoFRBMR)/linearSpring/linearSpring.C $(sDoFRBMR)/sphericalAngularSpring/sphericalAngularSpring.C +$(sDoFRBMR)/tabulatedAxialAngularSpring/tabulatedAxialAngularSpring.C sDoFRBMC = $(sDoFRBM)/sixDoFRigidBodyMotionConstraint diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/tabulatedAxialAngularSpring/tabulatedAxialAngularSpring.C b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/tabulatedAxialAngularSpring/tabulatedAxialAngularSpring.C new file mode 100644 index 0000000000..c2e164ecd8 --- /dev/null +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/tabulatedAxialAngularSpring/tabulatedAxialAngularSpring.C @@ -0,0 +1,230 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-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 + +\*---------------------------------------------------------------------------*/ + +#include "tabulatedAxialAngularSpring.H" +#include "addToRunTimeSelectionTable.H" +#include "sixDoFRigidBodyMotion.H" +#include "transform.H" +#include "unitConversion.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace sixDoFRigidBodyMotionRestraints +{ + defineTypeNameAndDebug(tabulatedAxialAngularSpring, 0); + addToRunTimeSelectionTable + ( + sixDoFRigidBodyMotionRestraint, + tabulatedAxialAngularSpring, + dictionary + ); +}; +}; + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::sixDoFRigidBodyMotionRestraints::tabulatedAxialAngularSpring:: +tabulatedAxialAngularSpring +( + const dictionary& sDoFRBMRDict +) +: + sixDoFRigidBodyMotionRestraint(sDoFRBMRDict), + refQ_(), + axis_(), + stiffness_(), + convertToDegrees_(), + damping_() +{ + read(sDoFRBMRDict); +} + + +// * * * * * * * * * * * * * * * * Destructors * * * * * * * * * * * * * * * // + +Foam::sixDoFRigidBodyMotionRestraints::tabulatedAxialAngularSpring:: +~tabulatedAxialAngularSpring() +{} + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +void +Foam::sixDoFRigidBodyMotionRestraints::tabulatedAxialAngularSpring::restrain +( + const sixDoFRigidBodyMotion& motion, + vector& restraintPosition, + vector& restraintForce, + vector& restraintMoment +) const +{ + vector refDir = rotationTensor(vector(1, 0 ,0), axis_) & vector(0, 1, 0); + + vector oldDir = refQ_ & refDir; + + vector newDir = motion.currentOrientation(refDir); + + if (mag(oldDir & axis_) > 0.95 || mag(newDir & axis_) > 0.95) + { + // Directions getting close to the axis, change reference + + refDir = rotationTensor(vector(1, 0 ,0), axis_) & vector(0, 0, 1); + + vector oldDir = refQ_ & refDir; + + vector newDir = motion.currentOrientation(refDir); + } + + // Removing any axis component from oldDir and newDir and normalising + oldDir -= (axis_ & oldDir)*axis_; + oldDir /= mag(oldDir); + + newDir -= (axis_ & newDir)*axis_; + newDir /= mag(newDir); + + scalar theta = mag(acos(oldDir & newDir)); + + // Temporary axis with sign information. + vector a = (oldDir ^ newDir); + + // Remove any component that is not along axis that may creep in + a = (a & axis_)*axis_; + + scalar magA = mag(a); + + if (magA > VSMALL) + { + a /= magA; + } + else + { + a = vector::zero; + } + + scalar stiffness; + + if (convertToDegrees_) + { + stiffness = stiffness_(radToDeg(theta)); + } + else + { + stiffness = stiffness_(theta); + } + + // Damping of along axis angular velocity only + restraintMoment = -stiffness*theta*a - damping_*(motion.omega() & a)*a; + + restraintForce = vector::zero; + + // Not needed to be altered as restraintForce is zero, but set to + // centreOfMass to be sure of no spurious moment + restraintPosition = motion.centreOfMass(); +} + + +bool Foam::sixDoFRigidBodyMotionRestraints::tabulatedAxialAngularSpring::read +( + const dictionary& sDoFRBMRDict +) +{ + sixDoFRigidBodyMotionRestraint::read(sDoFRBMRDict); + + refQ_ = sDoFRBMRCoeffs_.lookupOrDefault("referenceOrientation", I); + + if (mag(mag(refQ_) - sqrt(3.0)) > 1e-9) + { + FatalErrorIn + ( + "Foam::sixDoFRigidBodyMotionRestraints::" + "tabulatedAxialAngularSpring::read" + "(" + "const dictionary& sDoFRBMRDict" + ")" + ) + << "referenceOrientation " << refQ_ << " is not a rotation tensor. " + << "mag(referenceOrientation) - sqrt(3) = " + << mag(refQ_) - sqrt(3.0) << nl + << exit(FatalError); + } + + axis_ = sDoFRBMRCoeffs_.lookup("axis"); + + scalar magAxis(mag(axis_)); + + if (magAxis > VSMALL) + { + axis_ /= magAxis; + } + else + { + FatalErrorIn + ( + "Foam::sixDoFRigidBodyMotionRestraints::" + "tabulatedAxialAngularSpring::read" + "(" + "const dictionary& sDoFRBMCDict" + ")" + ) + << "axis has zero length" + << abort(FatalError); + } + + stiffness_ = interpolationTable(sDoFRBMRCoeffs_); + + word angleFormat = sDoFRBMRCoeffs_.lookup("angleFormat"); + + if (angleFormat == "degrees" || angleFormat == "degree") + { + convertToDegrees_ = true; + } + else if (angleFormat == "radians" || angleFormat == "radian") + { + convertToDegrees_ = false; + } + else + { + FatalErrorIn + ( + "Foam::sixDoFRigidBodyMotionRestraints::" + "tabulatedAxialAngularSpring::read" + "(" + "const dictionary& sDoFRBMCDict" + ")" + ) + << "angleFormat must be degree, degrees, radian or radians" + << abort(FatalError); + } + + sDoFRBMRCoeffs_.lookup("damping") >> damping_; + + return true; +} + +// ************************************************************************* // diff --git a/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/tabulatedAxialAngularSpring/tabulatedAxialAngularSpring.H b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/tabulatedAxialAngularSpring/tabulatedAxialAngularSpring.H new file mode 100644 index 0000000000..61c2c64197 --- /dev/null +++ b/src/postProcessing/functionObjects/forces/pointPatchFields/derived/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionRestraint/tabulatedAxialAngularSpring/tabulatedAxialAngularSpring.H @@ -0,0 +1,137 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-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 + Foam::sixDoFRigidBodyMotionRestraints::tabulatedAxialAngularSpring + +Description + sixDoFRigidBodyMotionRestraints model. Axial angular spring with stiffness + values drawn from an interpolation table. Linear damping. + +SourceFiles + tabulatedAxialAngularSpring.C + +\*---------------------------------------------------------------------------*/ + +#ifndef tabulatedAxialAngularSpring_H +#define tabulatedAxialAngularSpring_H + +#include "sixDoFRigidBodyMotionRestraint.H" +#include "point.H" +#include "tensor.H" +#include "interpolationTable.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +namespace sixDoFRigidBodyMotionRestraints +{ + +/*---------------------------------------------------------------------------*\ + Class tabulatedAxialAngularSpring Declaration +\*---------------------------------------------------------------------------*/ + +class tabulatedAxialAngularSpring +: + public sixDoFRigidBodyMotionRestraint +{ + // Private data + + //- Reference orientation where there is no moment + tensor refQ_; + + //- Global unit axis around which the motion is sprung + vector axis_; + + //- Spring stiffness coefficient interpolation table (Nm/rad + // or Nm/deg, depending on angleFormat) + interpolationTable stiffness_; + + //- Boolean stating whether the angle around the axis needs to + // be converted to degrees before asking the + // interpolationTable for a value + bool convertToDegrees_; + + //- Damping coefficient (Nms/rad) + scalar damping_; + + +public: + + //- Runtime type information + TypeName("tabulatedAxialAngularSpring"); + + + // Constructors + + //- Construct from components + tabulatedAxialAngularSpring + ( + const dictionary& sDoFRBMRDict + ); + + //- Construct and return a clone + virtual autoPtr clone() const + { + return autoPtr + ( + new tabulatedAxialAngularSpring(*this) + ); + } + + + // Destructor + + virtual ~tabulatedAxialAngularSpring(); + + + // Member Functions + + //- Calculate the restraint position, force and moment. + // Global reference frame vectors. + virtual void restrain + ( + const sixDoFRigidBodyMotion& motion, + vector& restraintPosition, + vector& restraintForce, + vector& restraintMoment + ) const; + + //- Update properties from given dictionary + virtual bool read(const dictionary& sDoFRBMRCoeff); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace solidBodyMotionFunctions +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* //