CppNoddy  0.92
Loading...
Searching...
No Matches
Utility.cpp
Go to the documentation of this file.
1/// \file Utility.cpp
2/// An implementation for a collection of utility functions.
3
4#include <string>
5#include <ctime>
6
7#include <Types.h>
8#include <Exceptions.h>
9#include <Utility.h>
10#include <FortranData.h>
11#include <FortranBLAS.h>
12
13namespace CppNoddy {
14 namespace Utility {
15
16
17 // template<>
18 // double OneD_Node_Mesh<double,double>::maxAbsLocation(unsigned var) {
19 // unsigned N = m_X.size();
20 // return dep_max_abs_location_range(var,m_X[0],m_X[N-1]);
21 // }
22
23 // template<>
24 // double OneD_Node_Mesh<double,double>::dep_max_abs_location_range(unsigned var, double left, double right) {
25 // double max(0.0);
26 // std::size_t maxIndex(0);
27 // // step through the nodes
28 // for(std::size_t node = 0; node < m_X.size(); ++node) {
29 // //std::cout << "m_X[node]=" << m_X[node] << " left=" << left << " right=" << right << "\n";
30 // if ( (m_X[node] >= left) && (m_X[node] <=right) ) {
31 // if(std::abs(m_vars[ node * m_nv + var ]) > max) {
32 // maxIndex = node;
33 // max = std::abs( m_vars[ maxIndex*m_nv + var ]);
34 // }
35 // }
36 // }
37 // if ( ( maxIndex == 0 ) || ( maxIndex == m_X.size()-1 ) ) {
38 // std::cout << "[WARNING] MaxAbsLocationRange: maximumum absolute nodal value is first/last node. \n";
39 // return m_X[ maxIndex ];
40 // }
41 // double f1,f2,f3;
42 // double x1,x2,x3;
43 // f1 = std::abs(m_vars[ (maxIndex-1) * m_nv + var ]);
44 // f2 = std::abs(m_vars[ maxIndex * m_nv + var ]);
45 // f3 = std::abs(m_vars[ (maxIndex+1) * m_nv + var ]);
46 // x1 = m_X[maxIndex-1];
47 // x2 = m_X[maxIndex];
48 // x3 = m_X[maxIndex+1];
49 // return ( f1*(x2+x3)/((x1-x2)*(x1-x3)) + f2*(x1+x3)/((x2-x1)*(x2-x3)) + f3*(x1+x2)/((x3-x1)*(x3-x2)) )
50 // / ( 2.*f1/((x1-x2)*(x1-x3)) + 2.*f2/((x2-x1)*(x2-x3)) + 2.*f3/((x3-x1)*(x3-x2)) );
51 // }
52
53
54 double max_abs_location(OneD_Node_Mesh<double> &mesh, unsigned var) {
55 double max(0.0);
56 std::size_t maxIndex(0);
57 // step through the nodes
58 for ( std::size_t node = 0; node < mesh.get_nnodes(); ++node ) {
59 //std::cout << "m_X[node]=" << m_X[node] << " left=" << left << " right=" << right << "\n";
60 if ( std::abs(mesh(node,var)) > max ) {
61 maxIndex = node;
62 max = std::abs( mesh(node,var) );
63 }
64 }
65 if ( ( maxIndex == 0 ) || ( maxIndex == mesh.get_nnodes()-1 ) ) {
66 std::cout << "[WARNING] MaxAbsLocationRange: maximumum absolute nodal value is first/last node. \n";
67 return mesh.coord( maxIndex );
68 }
69 double f1,f2,f3;
70 double x1,x2,x3;
71 f1 = std::abs(mesh(maxIndex-1,var));
72 f2 = std::abs(mesh(maxIndex,var));
73 f3 = std::abs(mesh(maxIndex+1,var));
74 x1 = mesh.coord(maxIndex-1);
75 x2 = mesh.coord(maxIndex);
76 x3 = mesh.coord(maxIndex+1);
77 return ( f1*(x2+x3)/((x1-x2)*(x1-x3)) + f2*(x1+x3)/((x2-x1)*(x2-x3)) + f3*(x1+x2)/((x3-x1)*(x3-x2)) )
78 / ( 2.*f1/((x1-x2)*(x1-x3)) + 2.*f2/((x2-x1)*(x2-x3)) + 2.*f3/((x3-x1)*(x3-x2)) );
79 }
80
81
82 double max_abs_location_range(OneD_Node_Mesh<double> &mesh, unsigned var, double left, double right ) {
83 double max(0.0);
84 std::size_t maxIndex(0);
85 // step through the nodes
86 for ( std::size_t node = 0; node < mesh.get_nnodes(); ++node ) {
87 //std::cout << "m_X[node]=" << m_X[node] << " left=" << left << " right=" << right << "\n";
88 if ( ( mesh.coord(node) >= left ) && ( mesh.coord(node) <= right ) ) {
89 if ( std::abs(mesh(node,var)) > max ) {
90 maxIndex = node;
91 max = std::abs( mesh(node,var) );
92 }
93 }
94 }
95 if ( ( maxIndex == 0 ) || ( maxIndex == mesh.get_nnodes()-1 ) ) {
96 std::cout << "[WARNING] MaxAbsLocationRange: maximumum absolute nodal value is first/last node. \n";
97 return mesh.coord( maxIndex );
98 }
99 double f1,f2,f3;
100 double x1,x2,x3;
101 f1 = std::abs(mesh(maxIndex-1,var));
102 f2 = std::abs(mesh(maxIndex,var));
103 f3 = std::abs(mesh(maxIndex+1,var));
104 x1 = mesh.coord(maxIndex-1);
105 x2 = mesh.coord(maxIndex);
106 x3 = mesh.coord(maxIndex+1);
107 return ( f1*(x2+x3)/((x1-x2)*(x1-x3)) + f2*(x1+x3)/((x2-x1)*(x2-x3)) + f3*(x1+x2)/((x3-x1)*(x3-x2)) )
108 / ( 2.*f1/((x1-x2)*(x1-x3)) + 2.*f2/((x2-x1)*(x2-x3)) + 2.*f3/((x3-x1)*(x3-x2)) );
109 }
110
111
112
113 DenseVector<double> uniform_node_vector(const double& lower, const double& upper, const std::size_t& N) {
115 V.reserve(N);
116 const double delta = (upper - lower) / (N - 1);
117 for(std::size_t i = 0; i < N; ++i) {
118 V.push_back(lower + delta * i);
119 }
120 return V;
121 }
122
123 DenseVector<double> power_node_vector(const double& lower, const double& upper, const std::size_t& N, const double& power) {
124 DenseVector<double> V(N, 0.0);
125 for(std::size_t i = 0; i < N; ++i) {
126 V[ i ] = lower + (upper - lower) * std::pow((double)i / (N - 1), power);
127 }
128 return V;
129 }
130
131 DenseVector<double> two_uniform_node_vector(const double& lower, const double& mid, const double& upper, const std::size_t& N1, const std::size_t& N2) {
132 DenseVector<double> first = uniform_node_vector(lower, mid, N1);
133 DenseVector<double> second = uniform_node_vector(mid, upper, N2 + 1);
134 // skip the common elt by starting at 1 not 0
135 for(std::size_t i = 1; i < N2+1; ++i) {
136 first.push_back(second[ i ]);
137 }
138 return first;
139 }
140
141 DenseVector<double> three_uniform_node_vector(const double& lower, const double& mid1, const double& mid2, const double& upper, const std::size_t& N1, const std::size_t& N2, const std::size_t& N3) {
142 DenseVector<double> first = uniform_node_vector(lower, mid1, N1);
143 DenseVector<double> second = uniform_node_vector(mid1, mid2, N2+1);
144 DenseVector<double> third = uniform_node_vector(mid2, upper, N3+1);
145 // skip the common elt by starting at 1 not 0
146 for(std::size_t i = 1; i < N2+1; ++i) {
147 first.push_back(second[ i ]);
148 }
149 for(std::size_t i = 1; i < N3+1; ++i) {
150 first.push_back(third[ i ]);
151 }
152 return first;
153 }
154
155 DenseVector<double> mid_weighted_node_vector(const double& lower, const double& upper, const std::size_t& N, const double& weight) {
156 DenseVector<double> node_vector(N, 0.0);
157 // make a center weighted distribution over -1 to 1
158 for(std::size_t i = 0; i < N; ++i) {
159 double s(-1.0 + 2.0 * i / (N - 1));
160 node_vector[ i ] = (weight * std::pow(s, 3) + s) / (weight + 1);
161 }
162 // map the -1 to 1 range to lower to upper
163 for(std::size_t i = 0; i < N; ++i) {
164 // move the range to 0->2
165 node_vector[ i ] += 1.0;
166 // move the range tp 0->1
167 node_vector[ i ] /= 2.0;
168 // move the range to lower -> upper
169 node_vector[ i ] *= (upper - lower);
170 node_vector[ i ] += lower;
171 }
172 return node_vector;
173 }
174
175
176
178 DenseVector<double> temp(X.size(), 0.0);
179 for(std::size_t i = 0; i < X.size(); ++i) {
180 temp[ i ] = X[ i ].real();
181 }
182 return temp;
183 }
184
186 DenseVector<double> temp(X.size(), 0.0);
187 for(std::size_t i = 0; i < X.size(); ++i) {
188 temp[ i ] = X[ i ].imag();
189 }
190 return temp;
191 }
192
193 std::string stringify(const int& val) {
194 std::stringstream temp;
195 temp << val;
196 return temp.str();
197 }
198
199 std::string stringify(const double& val, int p) {
200 std::stringstream temp;
201 temp.precision(p);
202 temp << val;
203 return temp.str();
204 }
205
206 // // dot product specialised for doubles to use
207 // // the BLAS library if LAPACK specified
208 // double dot<double>( const DenseVector<double>& X, const DenseVector<double>& Y )
209 // {
210 // // check lengths
211 // if ( X.size() != Y.size() )
212 // {
213 // std::string problem( " The LAPACK::dot method has detected a geometry error. \n" );
214 // throw ExceptionGeom( problem, X.size(), Y.size() );
215 // }
216 //#ifndef LAPACK
217 // double sum( 0.0 );
218 // inner_product( X.begin(), X.end(), Y.begin(), sum );
219 // return sum;
220 //#else
221 // return BLAS_DDOT( X.size(), &X[0], 1, &Y[0], 1 );
222 //#endif
223 // }
224
226#ifndef LAPACK
227 std::string problem;
228 problem = "The Utilities::multiply method has been called\n";
229 problem += "but the compiler option -DLAPACK was not provided when\n";
230 problem += "the library was built. This non-member function requires BLAS.";
231 throw ExceptionExternal(problem);
232#else
233 // set the matrix geometries
234 std::size_t M = A.nrows();
235 std::size_t N = B.ncols();
236 std::size_t K = A.ncols();
237 // No need to transpose first, because we will in fact do B^T * A^T = C^T
238 // New the memory for the result
239 FortranData Af(A, false);
240 FortranData Bf(B, false);
241 FortranData Cf(M * N);
242#ifdef PARANOID
243
244 if(K != B.nrows()) {
245 std::string problem(" The LAPACK::multiply method has detected a failure \n");
246 throw ExceptionGeom(problem, A.nrows(), A.ncols(), B.nrows(), B.ncols());
247 }
248#endif
249 // call Fortran BLAS
250 // call Fortran BLAS
251 BLAS_DGEMM((char*) "N", (char*) "N", N, M, K, 1.0, Bf.base(), N, Af.base(), K, 0.0, Cf.base(), N);
252 // Return a DenseMatrix<double> from the results -- since Cf is in column_major
253 // format, this will actually transpose the Cf data to provide C as required
254 return (Cf.to_dense_matrix(M, N));
255#endif
256
257 }
258
259 }
260
261} // end namespace
@ V
Definition: BVPKarman.cpp:20
The collection of CppNoddy exceptions.
Some interface definitions for calling external fortran routines from BLAS.
#define BLAS_DGEMM(TRANSA, TRANSB, M, N, K, ALPHA, A, LDA, B, LDB, BETA, C, LDC)
The BLAS DOUBLE dot-product Fortran interface : FUNCTION DDOT(N,X,INCX,Y,INCY)
Definition: FortranBLAS.h:19
A spec for a collection of utility functions.
A matrix class that constructs a DENSE matrix as a row major std::vector of DenseVectors.
Definition: DenseMatrix.h:25
std::size_t nrows() const
Definition: DenseMatrix.h:375
std::size_t ncols() const
Definition: DenseMatrix.h:380
An DenseVector class – a dense vector object.
Definition: DenseVector.h:34
void push_back(const _Type &fill)
A pass-thru definition of push_back.
Definition: DenseVector.h:310
std::size_t size() const
A pass-thru definition to get the size of the vector.
Definition: DenseVector.h:330
An exception to indicate that an error has been detected in an external (LAPACK) routine.
Definition: Exceptions.h:20
An exception class to be thrown when a container of incorrect geometry used in any class/method.
Definition: Exceptions.h:47
A little (legacy) utility class for passing CppNoddy containers to Fortran library routines.
Definition: FortranData.h:13
DenseMatrix< double > to_dense_matrix(std::size_t rows, std::size_t cols)
Convert the data to a double dense format.
Definition: FortranData.h:100
double * base()
Get the pointer to the first element.
Definition: FortranData.h:80
A one dimensional mesh utility object.
const _Xtype & coord(const std::size_t &node) const
Access a nodal position.
std::size_t get_nnodes() const
DenseVector< double > real(const DenseVector< D_complex > &X)
Return a double DENSE vector containing the real part of a complex DENSE vector.
Definition: Utility.cpp:177
DenseMatrix< double > multiply(DenseMatrix< double > &A, DenseMatrix< double > &B)
BLAS wrapper to do DOUBLE DENSE A_{MxK} * B_{KxN} = C_{MxN} Since this is a Fortran library,...
Definition: Utility.cpp:225
DenseVector< double > three_uniform_node_vector(const double &lower, const double &mid1, const double &mid2, const double &upper, const std::size_t &N1, const std::size_t &N2, const std::size_t &N3)
Return a dense vector with two uniform distributions in two separate regions.
Definition: Utility.cpp:141
DenseVector< double > power_node_vector(const double &lower, const double &upper, const std::size_t &N, const double &power)
Return a DENSE vector with the nodal points of a non-uniform mesh distributed between the upper/lower...
Definition: Utility.cpp:123
DenseVector< double > mid_weighted_node_vector(const double &lower, const double &upper, const std::size_t &N, const double &power)
Return a dense vector of nodal positions with more nodes concentrated at the mid point of the range.
Definition: Utility.cpp:155
DenseVector< double > two_uniform_node_vector(const double &lower, const double &mid, const double &upper, const std::size_t &N1, const std::size_t &N2)
Return a dense vector with two uniform distributions in two separate regions.
Definition: Utility.cpp:131
double max_abs_location(OneD_Node_Mesh< double > &mesh, unsigned var)
Definition: Utility.cpp:54
DenseVector< double > imag(const DenseVector< D_complex > &X)
Return a double DENSE vector containing the imaginary part of a complex DENSE vector.
Definition: Utility.cpp:185
double max_abs_location_range(OneD_Node_Mesh< double > &mesh, unsigned var, double left, double right)
Definition: Utility.cpp:82
std::string stringify(const int &val)
Return an integer value as a string - useful for file naming.
Definition: Utility.cpp:193
DenseVector< double > uniform_node_vector(const double &lower, const double &upper, const std::size_t &N)
Return a DENSE vector with the nodal points of a uniform mesh distributed between the upper/lower bou...
Definition: Utility.cpp:113
A collection of OO numerical routines aimed at simple (typical) applied problems in continuum mechani...

© 2012

R.E. Hewitt