void ParsedVelocitySource<Mu>::compute_postprocessed_quantity( unsigned int quantity_index, const AssemblyContext& context, const libMesh::Point& point, libMesh::Real& value ) { libMesh::DenseVector<libMesh::Number> output_vec(3); if( quantity_index == this->_parsed_velocity_source_x_index ) { (*this->velocity_source_function)(context, point, context.time, output_vec); value = output_vec(0); } else if( quantity_index == this->_parsed_velocity_source_y_index ) { (*this->velocity_source_function)(context, point, context.time, output_vec); value = output_vec(1); } else if( quantity_index == this->_parsed_velocity_source_z_index ) { (*this->velocity_source_function)(context, point, context.time, output_vec); value = output_vec(2); } return; }
int main() { // Change this type definition to double if your gpu supports that typedef float ScalarType; // Create vectors of eight complex values (represented as pairs of floating point values: [real_0, imag_0, real_1, imag_1, etc.]) viennacl::vector<ScalarType> input_vec(16); viennacl::vector<ScalarType> output_vec(16); // Fill with values (use viennacl::copy() for larger data!) for (std::size_t i=0; i<input_vec.size(); ++i) { if (i%2 == 0) input_vec(i) = ScalarType(i/2); // even indices represent real part else input_vec(i) = 0; // odd indices represent imaginary part } // Print the vector std::cout << "input_vec: " << input_vec << std::endl; // Compute FFT and store result in 'output_vec' std::cout << "Computing FFT..." << std::endl; viennacl::fft(input_vec, output_vec); // Compute FFT and store result directly in 'input_vec' viennacl::inplace_fft(input_vec); // Print result std::cout << "input_vec: " << input_vec << std::endl; std::cout << "output_vec: " << output_vec << std::endl; std::cout << "Computing inverse FFT..." << std::endl; viennacl::ifft(input_vec, output_vec); // either store result into output_vec viennacl::inplace_ifft(input_vec); // or compute in-place std::cout << "input_vec: " << input_vec << std::endl; std::cout << "output_vec: " << output_vec << std::endl; // // That's it. // std::cout << "!!!! TUTORIAL COMPLETED SUCCESSFULLY !!!!" << std::endl; return EXIT_SUCCESS; }
void VelocityPenalty<Mu>::compute_postprocessed_quantity( unsigned int quantity_index, const AssemblyContext& context, const libMesh::Point& point, libMesh::Real& value ) { libMesh::DenseVector<libMesh::Number> output_vec(3); if( quantity_index == this->_velocity_penalty_x_index ) { (*this->normal_vector_function)(context, point, context.time, output_vec); value = output_vec(0); } else if( quantity_index == this->_velocity_penalty_y_index ) { (*this->normal_vector_function)(context, point, context.time, output_vec); value = output_vec(1); } else if( quantity_index == this->_velocity_penalty_z_index ) { (*this->normal_vector_function)(context, point, context.time, output_vec); value = output_vec(2); } else if( quantity_index == this->_velocity_penalty_base_x_index ) { (*this->base_velocity_function)(context, point, context.time, output_vec); value = output_vec(0); } else if( quantity_index == this->_velocity_penalty_base_y_index ) { (*this->base_velocity_function)(context, point, context.time, output_vec); value = output_vec(1); } else if( quantity_index == this->_velocity_penalty_base_z_index ) { (*this->base_velocity_function)(context, point, context.time, output_vec); value = output_vec(2); } return; }
/** * In the main()-routine we create a few vectors and matrices and then run FFT on them. **/ int main() { // Feel free to change this type definition to double if your gpu supports that typedef float ScalarType; // Create vectors of eight complex values (represented as pairs of floating point values: [real_0, imag_0, real_1, imag_1, etc.]) viennacl::vector<ScalarType> input_vec(16); viennacl::vector<ScalarType> output_vec(16); viennacl::vector<ScalarType> input2_vec(16); viennacl::matrix<ScalarType> m(4, 8); viennacl::matrix<ScalarType> o(4, 8); for (std::size_t i = 0; i < m.size1(); i++) for (std::size_t s = 0; s < m.size2(); s++) m(i, s) = ScalarType((i + s) / 2); /** * Fill the vectors and matrices with values by using operator(). Use viennacl::copy() for larger data! **/ for (std::size_t i = 0; i < input_vec.size(); ++i) { if (i % 2 == 0) { input_vec(i) = ScalarType(i / 2); // even indices represent real part input2_vec(i) = ScalarType(i / 2); } else input_vec(i) = 0; // odd indices represent imaginary part } /** * Compute the FFT and store result in 'output_vec' **/ std::cout << "Computing FFT Matrix" << std::endl; std::cout << "m: " << m << std::endl; std::cout << "o: " << o << std::endl; viennacl::fft(m, o); std::cout << "Done" << std::endl; std::cout << "m: " << m << std::endl; std::cout << "o: " << o << std::endl; std::cout << "Transpose" << std::endl; viennacl::linalg::transpose(m, o); //viennacl::linalg::transpose(m); std::cout << "m: " << m << std::endl; std::cout << "o: " << o << std::endl; std::cout << "---------------------" << std::endl; /** * Compute the FFT using the Bluestein algorithm (usually faster, but higher memory footprint) **/ std::cout << "Computing FFT bluestein" << std::endl; // Print the vector std::cout << "input_vec: " << input_vec << std::endl; std::cout << "Done" << std::endl; viennacl::linalg::bluestein(input_vec, output_vec, 0); std::cout << "input_vec: " << input_vec << std::endl; std::cout << "output_vec: " << output_vec << std::endl; std::cout << "---------------------" << std::endl; /** * Computing the standard radix-FFT for a vector **/ std::cout << "Computing FFT " << std::endl; // Print the vector std::cout << "input_vec: " << input_vec << std::endl; std::cout << "Done" << std::endl; viennacl::fft(input_vec, output_vec); std::cout << "input_vec: " << input_vec << std::endl; std::cout << "output_vec: " << output_vec << std::endl; std::cout << "---------------------" << std::endl; /** * Computing the standard inverse radix-FFT for a vector **/ std::cout << "Computing inverse FFT..." << std::endl; //viennacl::ifft(output_vec, input_vec); // either store result into output_vec viennacl::inplace_ifft(output_vec); // or compute in-place std::cout << "input_vec: " << input_vec << std::endl; std::cout << "output_vec: " << output_vec << std::endl; std::cout << "---------------------" << std::endl; /** * Convert a real vector to an interleaved complex vector and back. * Entries with even indices represent real parts, odd indices imaginary parts. **/ std::cout << "Computing real to complex..." << std::endl; std::cout << "input_vec: " << input_vec << std::endl; viennacl::linalg::real_to_complex(input_vec, output_vec, input_vec.size() / 2); // or compute in-place std::cout << "output_vec: " << output_vec << std::endl; std::cout << "---------------------" << std::endl; std::cout << "Computing complex to real..." << std::endl; std::cout << "input_vec: " << input_vec << std::endl; //viennacl::ifft(output_vec, input_vec); // either store result into output_vec viennacl::linalg::complex_to_real(input_vec, output_vec, input_vec.size() / 2); // or compute in-place std::cout << "output_vec: " << output_vec << std::endl; std::cout << "---------------------" << std::endl; /** * Point-wise multiplication of two complex vectors. **/ std::cout << "Computing multiply complex" << std::endl; // Print the vector std::cout << "input_vec: " << input_vec << std::endl; std::cout << "input2_vec: " << input2_vec << std::endl; viennacl::linalg::multiply_complex(input_vec, input2_vec, output_vec); std::cout << "Done" << std::endl; std::cout << "output_vec: " << output_vec << std::endl; std::cout << "---------------------" << std::endl; /** * That's it. **/ std::cout << "!!!! TUTORIAL COMPLETED SUCCESSFULLY !!!!" << std::endl; return EXIT_SUCCESS; }
bool AveragedFanBase<Mu>::compute_force ( const libMesh::Point& point, const libMesh::Real time, const libMesh::NumberVectorValue& U, libMesh::NumberVectorValue& F, libMesh::NumberTensorValue *dFdU) { // Find base velocity of moving fan at this point libMesh::DenseVector<libMesh::Number> output_vec(3); base_velocity_function(point, time, output_vec); const libMesh::NumberVectorValue U_B(output_vec(0), output_vec(1), output_vec(2)); const libMesh::Number U_B_size = U_B.norm(); // If there's no base velocity there's no fan if (!U_B_size) return false; // Normal in fan velocity direction const libMesh::NumberVectorValue N_B = libMesh::NumberVectorValue(U_B/U_B_size); local_vertical_function(point, time, output_vec); // Normal in fan vertical direction const libMesh::NumberVectorValue N_V(output_vec(0), output_vec(1), output_vec(2)); // Normal in radial direction (or opposite radial direction, // for fans turning clockwise!) const libMesh::NumberVectorValue N_R = N_B.cross(N_V); // Fan-wing-plane component of local relative velocity const libMesh::NumberVectorValue U_P = U - (U*N_R)*N_R - U_B; const libMesh::Number U_P_size = U_P.norm(); // If there's no flow in the fan's frame of reference, there's no // lift or drag. FIXME - should we account for drag in the // out-of-plane direction? if (!U_P_size) return false; // Direction opposing drag const libMesh::NumberVectorValue N_drag = libMesh::NumberVectorValue(-U_P/U_P_size); // Direction opposing lift const libMesh::NumberVectorValue N_lift = N_drag.cross(N_R); // "Forward" velocity const libMesh::Number u_fwd = -(U_P * N_B); // "Upward" velocity const libMesh::Number u_up = U_P * N_V; // If there's no forward or upward velocity we should have already // returned false libmesh_assert (u_up || u_fwd); // Angle WRT fan velocity direction const libMesh::Number part_angle = std::atan2(u_up, u_fwd); // Angle WRT fan chord const libMesh::Number angle = part_angle + aoa_function(point, time); const libMesh::Number C_lift = lift_function(point, angle); const libMesh::Number C_drag = drag_function(point, angle); const libMesh::Number chord = chord_function(point, time); const libMesh::Number area = area_swept_function(point, time); const libMesh::Number v_sq = U_P*U_P; const libMesh::Number LDfactor = 0.5 * this->_rho * v_sq * chord / area; const libMesh::Number lift = C_lift * LDfactor; const libMesh::Number drag = C_drag * LDfactor; // Force F = lift * N_lift + drag * N_drag; if (dFdU) { // FIXME: Jacobians here are very inexact! // Dropping all AoA dependence on U terms! const libMesh::NumberVectorValue LDderivfactor = (N_lift*C_lift+N_drag*C_drag) * this->_rho * chord / area; for (unsigned int i=0; i != 3; ++i) for (unsigned int j=0; j != 3; ++j) (*dFdU)(i,j) = LDderivfactor(i) * U_P(j); } return true; }
bool VelocityPenaltyBase<Mu>::compute_force ( const libMesh::Point& point, const libMesh::Real time, const libMesh::NumberVectorValue& U, libMesh::NumberVectorValue& F, libMesh::NumberTensorValue *dFdU) { // Velocity discrepancy (current velocity minus base velocity) // normal to constraint plane, scaled by constraint penalty // value libmesh_assert(normal_vector_function.get()); libmesh_assert(base_velocity_function.get()); libMesh::DenseVector<libMesh::Number> output_vec(3); (*normal_vector_function)(point, time, output_vec); libMesh::NumberVectorValue U_N(output_vec(0), output_vec(1), output_vec(2)); (*base_velocity_function)(point, time, output_vec); const libMesh::NumberVectorValue U_B(output_vec(0), output_vec(1), output_vec(2)); const libMesh::NumberVectorValue U_Rel = U-U_B; // Old code // const libMesh::NumberVectorValue F1 = (U_Rel*U_N)*U_N; // // With correct sign and more natural normalization const libMesh::Number U_N_mag = std::sqrt(U_N*U_N); if (!U_N_mag) return false; const libMesh::NumberVectorValue U_N_unit = U_N/U_N_mag; F = -(U_Rel*U_N)*U_N_unit; if (dFdU) for (unsigned int i=0; i != 3; ++i) for (unsigned int j=0; j != 3; ++j) (*dFdU)(i,j) = -(U_N(j))*U_N_unit(i); // With quadratic scaling if (_quadratic_scaling) { const libMesh::Number U_Rel_mag = std::sqrt(U_Rel * U_Rel); // Modify dFdU first so as to reuse the old value of F if (dFdU) { // dU_Rel/dU = I // d(U_Rel*U_Rel)/dU = 2*U_Rel // d|U_Rel|/dU = U_Rel/|U_Rel| const libMesh::NumberVectorValue U_Rel_unit = U_Rel/U_Rel_mag; (*dFdU) *= U_Rel_mag; if (U_Rel_mag) for (unsigned int i=0; i != 3; ++i) for (unsigned int j=0; j != 3; ++j) (*dFdU)(i,j) += F(i)*U_Rel_unit(j); } F *= U_Rel_mag; } // With correction term to avoid doing work on flow bool do_correction = false; if (do_correction) { if (dFdU) libmesh_not_implemented(); const libMesh::Number U_Rel_mag_sq = U_Rel * U_Rel; if (U_Rel_mag_sq) { F -= (U_Rel*F)*U_Rel/U_Rel_mag_sq; } } return true; }