diff --git a/sdpm/CMakeLists.txt b/sdpm/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..dfa6b125378eee97b52e57c4df1aa2277ae1fada --- /dev/null +++ b/sdpm/CMakeLists.txt @@ -0,0 +1,28 @@ +# Copyright 2020 University of Liège +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Add source dir +ADD_SUBDIRECTORY( src ) +ADD_SUBDIRECTORY( _src ) + +# Add test dir +MACRO_AddTest(${CMAKE_CURRENT_SOURCE_DIR}/tests) + +# Add to install +INSTALL(FILES ${CMAKE_CURRENT_LIST_DIR}/__init__.py + ${CMAKE_CURRENT_LIST_DIR}/utils.py + DESTINATION sdpm) +INSTALL(DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/api + ${CMAKE_CURRENT_LIST_DIR}/viscous + DESTINATION sdpm) diff --git a/sdpm/__init__.py b/sdpm/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..b2401ae7a4f7757f92a1d10ba2ec8efc6022e36f --- /dev/null +++ b/sdpm/__init__.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# dart MODULE initialization file + +# Copyright 2020 University of Liège +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import fwk +import tbox +from sdpmw import * diff --git a/sdpm/_src/CMakeLists.txt b/sdpm/_src/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..38adbaead554a94fa178f13d9426e07a46ea102f --- /dev/null +++ b/sdpm/_src/CMakeLists.txt @@ -0,0 +1,35 @@ +# Copyright 2020 University of Liège +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# CMake input file of the SWIG wrapper around "spmw.so" + +INCLUDE(${SWIG_USE_FILE}) + +FILE(GLOB SRCS *.h *.cpp *.inl *.swg) +FILE(GLOB ISRCS *.i) + +SET_SOURCE_FILES_PROPERTIES(${ISRCS} PROPERTIES CPLUSPLUS ON) +SET(CMAKE_SWIG_FLAGS "-interface" "_sdpmw") # avoids "import _module_d" with MSVC/Debug +SWIG_ADD_LIBRARY(sdpmw LANGUAGE python SOURCES ${ISRCS} ${SRCS}) +SET_PROPERTY(TARGET sdpmw PROPERTY SWIG_USE_TARGET_INCLUDE_DIRECTORIES ON) +MACRO_DebugPostfix(sdpmw) + +TARGET_INCLUDE_DIRECTORIES(sdpmw PRIVATE ${PROJECT_SOURCE_DIR}/sdpm/_src + ${PROJECT_SOURCE_DIR}/ext/amfe/tbox/_src + ${PROJECT_SOURCE_DIR}/ext/amfe/fwk/_src + ${PYTHON_INCLUDE_PATH}) +TARGET_LINK_LIBRARIES(sdpmw PRIVATE sdpm tbox fwk ${PYTHON_LIBRARIES}) + +INSTALL(FILES ${EXECUTABLE_OUTPUT_PATH}/\${BUILD_TYPE}/sdpmw.py DESTINATION ${CMAKE_INSTALL_PREFIX}) +INSTALL(TARGETS sdpmw DESTINATION ${CMAKE_INSTALL_PREFIX}) diff --git a/sdpm/_src/sdpmw.h b/sdpm/_src/sdpmw.h new file mode 100644 index 0000000000000000000000000000000000000000..ee069ab530e48f8f14def0dbb60a31af1f6f755d --- /dev/null +++ b/sdpm/_src/sdpmw.h @@ -0,0 +1,18 @@ +/* + * Copyright 2020 University of Liège + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pPanels.h" +#include "pSDSolver.h" \ No newline at end of file diff --git a/sdpm/_src/sdpmw.i b/sdpm/_src/sdpmw.i new file mode 100644 index 0000000000000000000000000000000000000000..e039abc6192354cff08b699bcc1e4b2b1b858f14 --- /dev/null +++ b/sdpm/_src/sdpmw.i @@ -0,0 +1,47 @@ +/* + * Copyright 2020 University of Liège + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// SWIG input file of the 'dart' module + +%feature("autodoc","1"); + +%module(docstring= +"'sdpmw' module: Viscous inviscid interaction for dart 2021-2022 +(c) ULiege - A&M", +directors="0", +threads="1" +) sdpmw +%{ + +#include "sdpm.h" + +#include "fwkw.h" +#include "tboxw.h" +#include "sdpmw.h" + +%} + + +%include "fwkw.swg" + +// ----------- MODULES UTILISES ------------ +%import "tboxw.i" + +// ----------- FLOW CLASSES ---------------- +%include "sdpm.h" + +%include "pPanels.h" +%include "pSDSolver.h" \ No newline at end of file diff --git a/sdpm/src/CMakeLists.txt b/sdpm/src/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..aa9c304e587744d5df3bbef761c8a07129b5ec32 --- /dev/null +++ b/sdpm/src/CMakeLists.txt @@ -0,0 +1,27 @@ +# Copyright 2020 University of Liège +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# CMake input file of dart.so + +FILE(GLOB SRCS *.h *.cpp *.inl *.hpp) + +ADD_LIBRARY(sdpm SHARED ${SRCS}) +MACRO_DebugPostfix(sdpm) +TARGET_INCLUDE_DIRECTORIES(sdpm PUBLIC ${PROJECT_SOURCE_DIR}/sdpm/src) + +TARGET_LINK_LIBRARIES(sdpm tbox) + +INSTALL(TARGETS sdpm DESTINATION ${CMAKE_INSTALL_PREFIX}) + +SOURCE_GROUP(base REGULAR_EXPRESSION ".*\\.(cpp|inl|hpp|h)") diff --git a/sdpm/src/pPanels.cpp b/sdpm/src/pPanels.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f9305723db3f61994fdbd445c33126f7c1d6f8b7 --- /dev/null +++ b/sdpm/src/pPanels.cpp @@ -0,0 +1,657 @@ +#include "pPanels.h" +#include<iostream> +#include <Eigen/Dense> +#include <cmath> +#include "math.h" + +using namespace sdpm; + +Panels::Panels(size_t _nPanChord) +{ + nPanChord = _nPanChord; + nPanSpan = 2; + beta = 1; +} + +void Panels::CreateWing() +{ + Eigen::RowVectorXd xp(2*nPanChord+1); // Non-linear chordwise distribution + Eigen::RowVectorXd xc(2*nPanChord+1); // Control point chordwise distribution + + Eigen::RowVectorXd dumm = Eigen::VectorXd::LinSpaced(2*nPanChord+1, 0, M_PI); + for (auto i=0; i<xp.size(); ++i) + { + xp(i) = 1-std::sin(dumm(i)); + } + + for (auto i=0; i<xp.size(); ++i) + { + xc(i) = (xp(i+1) + xp(i))/2; + } + + /* Non-linear spanwise distribution */ + + Eigen::RowVectorXd yp(nPanSpan+1); + Eigen::RowVectorXd yc(nPanSpan); + Eigen::RowVectorXd theta = Eigen::RowVectorXd::LinSpaced(nPanSpan+1, M_PI, 0); + for (auto i=0; i<theta.size(); ++i) + { + yp(i) = std::cos(theta(i)); + } + + for (auto i=0; i<yc.size(); ++i) + { + yc(i) = (yp(i+1) + yp(i)) / 2; + } + + /* Spanwise chord variation */ + Eigen::RowVectorXd cvar; + cvar = (lambda-1)*c0*yp.cwiseAbs(); + cvar += c0 * Eigen::MatrixXd::Ones(1, cvar.size()); + Eigen::RowVectorXd epsilonvar; + epsilonvar=epsilon*yp.cwiseAbs(); + + /* Spanwise quarter chord distance due to twist */ + Eigen::RowVectorXd xsweep; + xsweep = std::tan(LambdaC4)*yp.cwiseAbs()*b/2; + /* Spanwise vertical distance due to dihedral */ + Eigen::RowVectorXd zdih; + zdih = std::tan(dihedral)*yp.cwiseAbs()*b/2; + + + /* Calculate airfoil shape at each panel gridpoint */ + + Eigen::MatrixXd zp = Eigen::MatrixXd::Zero(1,2*nPanChord+1); + + double t = .12; // Airfoil maximum thickness + + /* Upper side */ + + for (auto i=0; i<zp.size()/2; ++i) + { + zp(i) = -(t/0.2)*(0.2969*std::sqrt(xp(i)) - .126 * xp(i) - .3516* xp(i)*xp(i) + .2843*xp(i)*xp(i)*xp(i) - .1036*xp(i)*xp(i)*xp(i)*xp(i)); + } + + /* Lower side */ + + for (auto i=zp.size()/2; i<zp.size(); ++i) + { + zp(i) = (t/0.2)*(0.2969*std::sqrt(xp(i)) - .126 * xp(i) - .3516* xp(i)*xp(i) + .2843*xp(i)*xp(i)*xp(i) - .1036*xp(i)*xp(i)*xp(i)*xp(i)); + } + + // iko=find(xp <= maxpos); + // zp(iko)=zp(iko)+maxcamb/maxpos^2*(2*maxpos*xp(iko)-xp(iko).^2); + // iko=find(xp > maxpos); + // zp(iko)=zp(iko)+maxcamb/(1-maxpos)^2*((1-2*maxpos)+2*maxpos*xp(iko)-xp(iko).^2); + + /* Assemble bound panel corner point matrices */ + /* Eigen::Array * Eigen::Array is a mult element wise while Eigen::Matrix * Eigen::Matrix is a matrix product -> cwiseProduct */ + Xp = xp.transpose().replicate(1,nPanSpan+1).cwiseProduct(cvar.replicate(2*nPanChord+1,1)) - cvar.replicate(2*nPanChord+1,1)*ax; + Yp = yp.replicate(2*nPanChord+1,1) * b/2; + Zp = zp.transpose().replicate(1,nPanSpan+1).cwiseProduct(cvar.replicate(2*nPanChord+1,1)); + + Surface = (c0+c0*lambda)/2 * b; + + + + // % Apply twist + // for i=1:n+1 + // Ry=(cos(epsilonvar(i)) sin(epsilonvar(i));-sin(epsilonvar(i)) cos(epsilonvar(i))); + // dummy=Ry*(Xp(:,i)';Zp(:,i)'); + // Xp(:,i)=dummy(1,:)'; + // Zp(:,i)=dummy(2,:)'; + // end + + // % Apply dihedral + // Zp=Zp+repmat(zdih,2*m+1,1); + // % Apply sweep + // Xp=Xp+repmat(xsweep,2*m+1,1); + + Xc.setZero(2*nPanChord, nPanSpan); + Yc.setZero(2*nPanChord, nPanSpan); + Zc.setZero(2*nPanChord, nPanSpan); + nx.setZero(2*nPanChord, nPanSpan); + ny.setZero(2*nPanChord, nPanSpan); + nz.setZero(2*nPanChord, nPanSpan); + Xc0.setZero(2*nPanChord, nPanSpan); + Yc0.setZero(2*nPanChord, nPanSpan); + Zc0.setZero(2*nPanChord, nPanSpan); + nx0.setZero(2*nPanChord, nPanSpan); + ny0.setZero(2*nPanChord, nPanSpan); + nz0.setZero(2*nPanChord, nPanSpan); + tauxx.setZero(2*nPanChord, nPanSpan); + tauxy.setZero(2*nPanChord, nPanSpan); + tauxz.setZero(2*nPanChord, nPanSpan); + tauyx.setZero(2*nPanChord, nPanSpan); + tauyy.setZero(2*nPanChord, nPanSpan); + tauyz.setZero(2*nPanChord, nPanSpan); + s.setZero(2*nPanChord, nPanSpan); + s0.setZero(2*nPanChord, nPanSpan); + cpln.setZero(2*nPanChord, nPanSpan); + + for (size_t i=0; i<2*nPanChord; ++i) + { + for (size_t j=0; j<nPanSpan; ++j) + { + /* Calculate control points */ + Xc0(i,j) = (Xp(i,j) + Xp(i,j+1) + Xp(i+1,j+1) + Xp(i+1,j))/4; + Yc0(i,j) = (Yp(i,j) + Yp(i,j+1) + Yp(i+1,j+1) + Yp(i+1,j))/4; + Zc0(i,j) = (Zp(i,j) + Zp(i,j+1) + Zp(i+1,j+1) + Zp(i+1,j))/4; + + /* Calculate the normal vectors */ + /*(N,s0(i,j),cpln(i,j))=normalarea((Xp(i,j) Xp(i,j+1) Xp(i+1,j+1) Xp(i+1,j)), ... + (Yp(i,j) Yp(i,j+1) Yp(i+1,j+1) Yp(i+1,j)), ... + (Zp(i,j) Zp(i,j+1) Zp(i+1,j+1) Zp(i+1,j))); */ + + /* Normal vector (cross product) */ + Eigen::RowVector3d normal1 = Eigen::RowVector3d(Xp(i+1,j+1)-Xp(i,j), Yp(i+1,j+1)-Yp(i,j), Zp(i+1,j+1)-Zp(i,j)).cross(Eigen::RowVector3d(Xp(i,j+1)-Xp(i+1,j), Yp(i,j+1)-Yp(i+1,j), Zp(i,j+1)-Zp(i+1,j))); + Eigen::RowVectorXd mag1 = (normal1*normal1.transpose()); + mag1(0) = std::sqrt(mag1(0)); + normal1 /= mag1(0); // mag1 is of size 1 + + /* Calculate a second normal from points 1,2,3 only */ + Eigen::RowVector3d normal2= Eigen::RowVector3d(Xp(i+1,j+1)-Xp(i,j), Yp(i+1,j+1)-Yp(i,j), Zp(i+1,j+1)-Zp(i,j)).cross(Eigen::RowVector3d(Xp(i,j+1)-Xp(i,j), Yp(i,j+1)-Yp(i,j), Zp(i,j+1)-Zp(i,j))); + Eigen::RowVectorXd mag2=(normal2*normal2.transpose()); + mag2(0) = std::sqrt(mag2(0)); + normal2=normal2/mag2(0); + + /* Test if the two normals are colinear */ + cpln(i,j) = normal1.cross(normal2)(0); + Eigen::RowVectorXd dum1 = cpln*cpln.transpose(); + cpln(i,j)=sqrt(dum1(0)); + + /* Calculate a third normal from points 1,3,4 only */ + Eigen::RowVector3d normal3 = Eigen::RowVector3d(Xp(i+1,j+1)-Xp(i,j), Yp(i+1,j+1)-Yp(i,j), Zp(i+1,j+1)-Zp(i,j)).cross(Eigen::RowVector3d(Xp(i+1,j)-Xp(i,j), Yp(i+1,j)-Yp(i,j), Zp(i+1,j)-Zp(i,j))); + Eigen::RowVectorXd mag3=(normal3*normal3.transpose()); + mag3(0) = std::sqrt(mag3(0)); + /* Panel area */ + s0(i,j) = mag2(0)/2+mag3(0)/2; + + nx0(i,j) = normal1(0); + ny0(i,j) = normal1(1); + nz0(i,j) = normal1(2); + + } + } + + /* Scale for compressibility */ + /*Xp0=Xp; + Yp0=Yp; + Zp0=Zp; + Xp=Xp0/beta; // (beta = sqrt(1-M*M)) + Yp=Yp0; + Zp=Zp0;*/ + + for (size_t i=0 ; i<2*nPanChord; ++i) + { + for (size_t j=0; j<nPanSpan; ++j) + { + /* Calculate control points */ + Xc(i,j)=(Xp(i,j) + Xp(i,j+1) + Xp(i+1,j+1) + Xp(i+1,j))/4; + Yc(i,j)=(Yp(i,j) + Yp(i,j+1) + Yp(i+1,j+1) + Yp(i+1,j))/4; + Zc(i,j)=(Zp(i,j) + Zp(i,j+1) + Zp(i+1,j+1) + Zp(i+1,j))/4; + /* Calculate the normal vectors */ + /* (N,s(i,j),cpln(i,j))=normalarea((Xp(i,j) Xp(i,j+1) Xp(i+1,j+1) Xp(i+1,j)), ... + (Yp(i,j) Yp(i,j+1) Yp(i+1,j+1) Yp(i+1,j)), ... + (Zp(i,j) Zp(i,j+1) Zp(i+1,j+1) Zp(i+1,j))); */ + + /* Normal vector (cross product) */ + Eigen::RowVector3d normal1 = Eigen::RowVector3d(Xp(i+1,j+1)-Xp(i,j), Yp(i+1,j+1)-Yp(i,j), Zp(i+1,j+1)-Zp(i,j)).cross(Eigen::RowVector3d(Xp(i,j+1)-Xp(i+1,j), Yp(i,j+1)-Yp(i+1,j), Zp(i,j+1)-Zp(i+1,j))); + Eigen::RowVectorXd mag1 = (normal1*normal1.transpose()); + mag1(0) = std::sqrt(mag1(0)); + normal1 /= mag1(0); // mag1 is of size 1 + + /* Calculate a second normal from points 1,2,3 only */ + Eigen::RowVector3d normal2= Eigen::RowVector3d(Xp(i+1,j+1)-Xp(i,j), Yp(i+1,j+1)-Yp(i,j), Zp(i+1,j+1)-Zp(i,j)).cross(Eigen::RowVector3d(Xp(i,j+1)-Xp(i,j), Yp(i,j+1)-Yp(i,j), Zp(i,j+1)-Zp(i,j))); + Eigen::RowVectorXd mag2=(normal2*normal2.transpose()); + mag2(0) = std::sqrt(mag2(0)); + normal2=normal2/mag2(0); + + /* Test if the two normals are colinear */ + cpln(i,j) = normal1.cross(normal2)(0); + Eigen::RowVectorXd dum1 = cpln*cpln.transpose(); + cpln(i,j)=sqrt(dum1(0)); + + /* Calculate a third normal from points 1,3,4 only */ + Eigen::RowVector3d normal3 = Eigen::RowVector3d(Xp(i+1,j+1)-Xp(i,j), Yp(i+1,j+1)-Yp(i,j), Zp(i+1,j+1)-Zp(i,j)).cross(Eigen::RowVector3d(Xp(i+1,j)-Xp(i,j), Yp(i+1,j)-Yp(i,j), Zp(i+1,j)-Zp(i,j))); + Eigen::RowVectorXd mag3=(normal3*normal3.transpose()); + mag3(0) = std::sqrt(mag3(0)); + /* Panel area */ + s(i,j) = mag2(0)/2+mag3(0)/2; + + nx(i,j) = normal1(0); + ny(i,j) = normal1(1); + nz(i,j) = normal1(2); + + /* Calculate tangential vector in x direction */ + double a=1/sqrt(1+(normal1(0)/normal1(2))*(normal1(0)/normal1(2))); + double c=-normal1(0)/normal1(2)*a; + tauxx(i,j)=a; + tauxy(i,j)=0; + tauxz(i,j)=c; + + /* Calculate tangential vector in y direction */ + Eigen::RowVector3d dummy = normal1.cross(Eigen::RowVector3d(a, 0, c)); + tauyx(i,j)=dummy(0); + tauyy(i,j)=dummy(1); + tauyz(i,j)=dummy(2); + } + } + +} + +void Panels::WakeControlPoints(unsigned long it){ + for (size_t i=0; i<it; ++i){ + for (size_t j=0; j<nPanSpan; ++j) + { + + /* Calculate control points */ + Xcw(i,j) = (Xw(i,j) + Xw(i,j+1) + Xw(i+1,j+1) + Xw(i+1,j))/4; + Ycw(i,j) = (Yw(i,j) + Yw(i,j+1) + Yw(i+1,j+1) + Yw(i+1,j))/4; + Zcw(i,j) = (Zw(i,j) + Zw(i,j+1) + Zw(i+1,j+1) + Zw(i+1,j))/4; + /* Calculate the normal vectors */ + /* N=normalarea((Xw(i,j) Xw(i,j+1) Xw(i+1,j+1) Xw(i+1,j)), ... + (Yw(i,j) Yw(i,j+1) Yw(i+1,j+1) Yw(i+1,j)), ... + (Zw(i,j) Zw(i,j+1) Zw(i+1,j+1) Zw(i+1,j))); */ + + /* Normal vector (cross product) */ + Eigen::RowVector3d normal1 = Eigen::RowVector3d(Xw(i+1,j+1)-Xw(i,j), Yw(i+1,j+1)-Yw(i,j), Zw(i+1,j+1)-Zw(i,j)).cross(Eigen::RowVector3d(Xw(i,j+1)-Xw(i+1,j), Yw(i,j+1)-Yw(i+1,j), Zw(i,j+1)-Zw(i+1,j))); + Eigen::RowVectorXd mag1 = (normal1*normal1.transpose()); + mag1(0) = std::sqrt(mag1(0)); + normal1 /= mag1(0); // mag1 is of size 1 + + nxw(i,j) = normal1(0); + nyw(i,j) = normal1(1); + nzw(i,j) = normal1(2); + + /* Calculate tangential vector in x direction */ + double a= 1/sqrt(1+(normal1(0)/normal1(2))*(normal1(0)/normal1(2))); + double c=-normal1(0)/normal1(2)*a; + tauxxw(i,j)=a; + tauxyw(i,j)=0; + tauxzw(i,j)=c; + + /* Calculate tangential vector in y direction */ + Eigen::Vector3d dummy = normal1.cross(Eigen::Vector3d(a, 0, c)); + tauyxw(i,j)=dummy(0); + tauyyw(i,j)=dummy(1); + tauyzw(i,j)=dummy(2); + } + } +} + + +void Panels::ComputeInfluenceCoeffs_wing() +{ + /* Sources */ + AN.setZero(2*nPanChord*nPanSpan,2*nPanChord*nPanSpan); + Au.setZero(2*nPanChord*nPanSpan,2*nPanChord*nPanSpan); + Av.setZero(2*nPanChord*nPanSpan,2*nPanChord*nPanSpan); + Aw.setZero(2*nPanChord*nPanSpan,2*nPanChord*nPanSpan); + /* Doublets */ + BN.setZero(2*nPanChord*nPanSpan,2*nPanChord*nPanSpan); + Bu.setZero(2*nPanChord*nPanSpan,2*nPanChord*nPanSpan); + Bv.setZero(2*nPanChord*nPanSpan,2*nPanChord*nPanSpan); + Bw.setZero(2*nPanChord*nPanSpan,2*nPanChord*nPanSpan); + /* Call mex function to calculate influence coefficients of wing on wing */ + + Eigen::RowVectorXd x, y, z; + x.setZero(5); + y.setZero(5); + z.setZero(5); + + Eigen::RowVector3d normal; + Eigen::RowVector3d taux; + Eigen::RowVector3d tauy; + + Eigen::RowVector2d Phisd; + Eigen::RowVectorXd uvw; + uvw.setZero(6); + + double x0, y0, z0, xcp, ycp, zcp; + + size_t ic,jc,i,j; + + size_t m = Xc.rows(); + size_t n = Xc.cols(); + //size_t mp1=m+1; + //size_t np1=n+1; + //size_t mn=m*n; + + /* Create Influence Matrix */ + + for (ic=0; ic < m; ic++) { + for (jc=0; jc < n; jc++) { + for (i=0; i < m; i++) { + for (j=0; j < n; j++) { + x0=Xc(ic,jc); + y0=Yc(ic,jc); + z0=Zc(ic,jc); + xcp=Xc(i,j); + ycp=Yc(i,j); + zcp=Zc(i,j); + x(0)=Xp(i,j); + x(1)=Xp(i,(j+1)); + x(2)=Xp(i+1,(j+1)); + x(3)=Xp(i+1,j); + x(4)=Xp(i,j); + y(0)=Yp(i,j); + y(1)=Yp(i,(j+1)); + y(2)=Yp(i+1,(j+1)); + y(3)=Yp(i+1,j); + y(4)=Yp(i,j); + z(0)=Zp(i,j); + z(1)=Zp(i,(j+1)); + z(2)=Zp(i+1,(j+1)); + z(3)=Zp(i+1,j); + z(4)=Zp(i,j); + normal(0)=nx(i,j); + normal(1)=ny(i,j); + normal(2)=nz(i,j); + taux(0)=tauxx(i,j); + taux(1)=tauxy(i,j); + taux(2)=tauxz(i,j); + tauy(0)=tauyx(i,j); + tauy(1)=tauyy(i,j); + tauy(2)=tauyz(i,j); + + sdpanel_wing(Phisd,uvw,x0,y0,z0,x,y,z,xcp,ycp,zcp,normal,taux,tauy); + AN(ic*n+jc,i*n+j)=Phisd(0); + Bu(ic*n+jc,i*n+j)=-uvw(3); + Bv(ic*n+jc,i*n+j)=-uvw(4); + Bw(ic*n+jc,i*n+j)=-uvw(5); + if ((ic*n+jc) == (i*n+j)) { + Au(ic*n+jc,i*n+j)=normal(0)/2.0; + Av(ic*n+jc,i*n+j)=normal(1)/2.0; + Aw(ic*n+jc,i*n+j)=normal(2)/2.0; + BN(ic*n+jc,i*n+j)=-0.5; + }else{ + Au(ic*n+jc,i*n+j)=uvw(0); + Av(ic*n+jc,i*n+j)=uvw(1); + Aw(ic*n+jc,i*n+j)=uvw(2); + BN(ic*n+jc,i*n+j)=Phisd(1); + } + + } + } + } + } +} + +void Panels::sdpanel_wing(Eigen::RowVector2d &Phisd, Eigen::RowVectorXd &uvw, double x0, double y0, double z0, Eigen::RowVectorXd x, Eigen::RowVectorXd y, Eigen::RowVectorXd z, double xcp, double ycp, double zcp, + Eigen::RowVector3d normal, Eigen::RowVector3d taux, Eigen::RowVector3d tauy) +{ + + Eigen::RowVectorXd xl, yl, zl, r, e, h, mij, dij, rij, wij; + xl.setZero(5); + yl.setZero(5); + zl.setZero(5); + r.setZero(5); + e.setZero(5); + h.setZero(5); + + mij.setZero(4); + dij.setZero(4); + rij.setZero(4); + wij.setZero(4); + + double x0l,y0l,z0l; + double pi,Phi1,Phi2,logterm,logdenom,atanterm,fraction,fracdenom,xx,yy,us,vs,ws,ud,vd,wd; + int i; + + pi=3.14159265358979; + + for (i=0; i < 5; i++) { + xl(i)=(x(i)-xcp)*taux(0)+(y(i)-ycp)*taux(1)+(z(i)-zcp)*taux(2); + yl(i)=(x(i)-xcp)*tauy(0)+(y(i)-ycp)*tauy(1)+(z(i)-zcp)*tauy(2); + zl(i)=(x(i)-xcp)*normal(0)+(y(i)-ycp)*normal(1)+(z(i)-zcp)*normal(2); + } + x0l=(x0-xcp)*taux(0)+(y0-ycp)*taux(1)+(z0-zcp)*taux(2); + y0l=(x0-xcp)*tauy(0)+(y0-ycp)*tauy(1)+(z0-zcp)*tauy(2); + z0l=(x0-xcp)*normal(0)+(y0-ycp)*normal(1)+(z0-zcp)*normal(2); + + for (i=0; i < 4; i++) { + r(i)=sqrt((x0l-xl(i))*(x0l-xl(i))+(y0l-yl(i))*(y0l-yl(i))+z0l*z0l); + rij(i)=(x0l-xl(i))*(x0l-xl(i+1))+(y0l-yl(i))*(y0l-yl(i+1))+z0l*z0l; + wij(i)=(x0l-xl(i+1))*(y0l-yl(i))-(x0l-xl(i))*(y0l-yl(i+1)); + e(i)=(x0l-xl(i))*(x0l-xl(i))+z0l*z0l; + h(i)=(x0l-xl(i))*(y0l-yl(i)); + mij(i)=(yl(i+1)-yl(i))/(xl(i+1)-xl(i)); + dij(i)=sqrt((xl(i+1)-xl(i))*(xl(i+1)-xl(i))+(yl(i+1)-yl(i))*(yl(i+1)-yl(i))); + } + r(4)=r(0); + e(4)=e(0); + h(4)=h(0); + + Phi1=0.; + Phi2=0.; + us=0.; + vs=0.; + ud=0.; + vd=0.; + wd=0.; + for (i=0; i < 4; i++) { + logterm=0.0; + logdenom=(r(i)+r(i+1)-dij(i)); + if (fabs(logdenom) > 1e-10){ + logterm=log((r(i)+r(i+1)+dij(i))/logdenom); + } + us=us-(yl(i+1)-yl(i))*logterm/dij(i); + vs=vs-(xl(i)-xl(i+1))*logterm/dij(i); + Phi1+=((x0l-xl(i))*(yl(i+1)-yl(i))-(y0l-yl(i))*(xl(i+1)-xl(i)))/dij(i)*logterm; + atanterm=0.0; + if ((fabs(xl(i+1)-xl(i)) > 1e-10) && (fabs(z0l) > 1e-10)){ //mij(i) is not infinite + xx=(mij(i)*e(i)-h(i))/(z0l*r(i)); + yy=(mij(i)*e(i+1)-h(i+1))/(z0l*r(i+1)); + atanterm=atan2(xx-yy,1+xx*yy); + } + fraction=0.0; + fracdenom=r(i)*r(i+1)*(r(i)*r(i+1)+rij(i)); + if (fabs(fracdenom) > 1e-10){ + fraction=(r(i)+r(i+1))/fracdenom; + } + Phi2+=atanterm; + ud+=z0l*(yl(i)-yl(i+1))*fraction; + vd+=z0l*(xl(i+1)-xl(i))*fraction; + wd+=wij(i)*fraction; + } + // Source potential + Phisd(0)=-1/4.0/pi*(Phi1+fabs(z0l)*Phi2); +// Phisd(0)=-1/4.0/pi*(Phi1-z0l*Phi2); + // Source velocities + us=us/4.0/pi; + vs=vs/4.0/pi; + ws=Phi2/4.0/pi; + // Doublet potential + Phisd(1)=ws; + // Doublet velocities + ud=ud/4.0/pi; + vd=vd/4.0/pi; + wd=wd/4.0/pi; + + // Transform velocities to global coordinates + uvw(0)=taux(0)*us+tauy(0)*vs+normal(0)*ws; + uvw(1)=taux(1)*us+tauy(1)*vs+normal(1)*ws; + uvw(2)=taux(2)*us+tauy(2)*vs+normal(2)*ws; + uvw(3)=taux(0)*ud+tauy(0)*vd+normal(0)*wd; + uvw(4)=taux(1)*ud+tauy(1)*vd+normal(1)*wd; + uvw(5)=taux(2)*ud+tauy(2)*vd+normal(2)*wd; +} + +void Panels::ComputeInfluenceCoeffs_wake(unsigned long it) +{ + + CN.setZero(2*nPanChord*nPanSpan, nPanSpan*it); + Cu.setZero(2*nPanChord*nPanSpan, nPanSpan*it); + Cv.setZero(2*nPanChord*nPanSpan, nPanSpan*it); + Cw.setZero(2*nPanChord*nPanSpan, nPanSpan*it); + + Eigen::RowVectorXd x, y, z; + x.setZero(5); + y.setZero(5); + z.setZero(5); + + Eigen::RowVector3d normal; + Eigen::RowVector3d taux; + Eigen::RowVector3d tauy; + + Eigen::RowVectorXd Phisd; + Phisd.setZero(1); + Eigen::RowVectorXd uvw; + uvw.setZero(3); + + double x0, y0, z0, xcp, ycp, zcp; + + size_t ic,jc,i,j; + + size_t m = Xc.rows(); + size_t n = Xc.cols(); + //size_t mp1=m+1; + //size_t np1=n+1; + //size_t mn=m*n; + + size_t mwp1 = it+1; + size_t mw = mwp1-1; + + /* Create Influence Matrix */ + + for (ic=0; ic < m; ic++) { + for (jc=0; jc < n; jc++) { + for (i=0; i < mw; i++) { + for (j=0; j < n; j++) { + x0=Xc(ic,jc); + y0=Yc(ic,jc); + z0=Zc(ic,jc); + xcp=Xcw(i,j); + ycp=Ycw(i,j); + zcp=Zcw(i,j); + x(0)=Xw(i,j); + x(1)=Xw(i,(j+1)); + x(2)=Xw(i+1,(j+1)); + x(3)=Xw(i+1,j); + x(4)=Xw(i,j); + y(0)=Yw(i,j); + y(1)=Yw(i,(j+1)); + y(2)=Yw(i+1,(j+1)); + y(3)=Yw(i+1,j); + y(4)=Yw(i,j); + z(0)=Zw(i,j); + z(1)=Zw(i,(j+1)); + z(2)=Zw(i+1,(j+1)); + z(3)=Zw(i+1,j); + z(4)=Zw(i,j); + normal(0)=nxw(i,j); + normal(1)=nyw(i,j); + normal(2)=nzw(i,j); + taux(0)=tauxxw(i,j); + taux(1)=tauxyw(i,j); + taux(2)=tauxzw(i,j); + tauy(0)=tauyxw(i,j); + tauy(1)=tauyyw(i,j); + tauy(2)=tauyzw(i,j); + + sdpanel_wake(Phisd,uvw,x0,y0,z0,x,y,z,xcp,ycp,zcp,normal,taux,tauy); + CN(ic*n+jc, i*n+j)=Phisd(0); + Cu(ic*n+jc, i*n+j)=-uvw(0); + Cv(ic*n+jc, i*n+j)=-uvw(1); + Cw(ic*n+jc, i*n+j)=-uvw(2); + } + } + } + } +} + +void Panels::sdpanel_wake(Eigen::RowVectorXd &Phisd, Eigen::RowVectorXd &uvw,double x0, double y0, double z0, Eigen::RowVectorXd x, Eigen::RowVectorXd y, Eigen::RowVectorXd z, double xcp, double ycp, double zcp, + Eigen::RowVector3d normal, Eigen::RowVector3d taux, Eigen::RowVector3d tauy) +{ + + Eigen::RowVectorXd xl, yl, zl, r, e, h, mij, dij, rij, wij; + xl.setZero(5); + yl.setZero(5); + zl.setZero(5); + r.setZero(5); + e.setZero(5); + h.setZero(5); + + mij.setZero(4); + dij.setZero(4); + rij.setZero(4); + wij.setZero(4); + + double x0l,y0l,z0l; + double pi,Phi2,atanterm,xx,yy,fraction,fracdenom,ud,vd,wd; + int i; + + pi=3.14159265358979; + + for (i=0; i < 5; i++) { + xl(i)=(x(i)-xcp)*taux(0)+(y(i)-ycp)*taux(1)+(z(i)-zcp)*taux(2); + yl(i)=(x(i)-xcp)*tauy(0)+(y(i)-ycp)*tauy(1)+(z(i)-zcp)*tauy(2); + zl(i)=(x(i)-xcp)*normal(0)+(y(i)-ycp)*normal(1)+(z(i)-zcp)*normal(2); + } + x0l=(x0-xcp)*taux(0)+(y0-ycp)*taux(1)+(z0-zcp)*taux(2); + y0l=(x0-xcp)*tauy(0)+(y0-ycp)*tauy(1)+(z0-zcp)*tauy(2); + z0l=(x0-xcp)*normal(0)+(y0-ycp)*normal(1)+(z0-zcp)*normal(2); + + for (i=0; i < 4; i++) { + r(i)=sqrt((x0l-xl(i))*(x0l-xl(i))+(y0l-yl(i))*(y0l-yl(i))+z0l*z0l); + rij(i)=(x0l-xl(i))*(x0l-xl(i+1))+(y0l-yl(i))*(y0l-yl(i+1))+z0l*z0l; + wij(i)=(x0l-xl(i+1))*(y0l-yl(i))-(x0l-xl(i))*(y0l-yl(i+1)); + e(i)=(x0l-xl(i))*(x0l-xl(i))+z0l*z0l; + h(i)=(x0l-xl(i))*(y0l-yl(i)); + mij(i)=(yl(i+1)-yl(i))/(xl(i+1)-xl(i)); + dij(i)=sqrt((xl(i+1)-xl(i))*(xl(i+1)-xl(i))+(yl(i+1)-yl(i))*(yl(i+1)-yl(i))); + } + r(4)=r(0); + e(4)=e(0); + h(4)=h(0); + + Phi2=0; + ud=0.0; + vd=0.0; + wd=0.0; + for (i=0; i < 4; i++) { + atanterm=0; + if ((xl(i+1)-xl(i) != 0) && (z0l != 0)){ //mij(i) is not infinite + xx=(mij(i)*e(i)-h(i))/(z0l*r(i)); + yy=(mij(i)*e(i+1)-h(i+1))/(z0l*r(i+1)); + atanterm=atan2(xx-yy,1+xx*yy); + } + fraction=0.0; + fracdenom=r(i)*r(i+1)*(r(i)*r(i+1)+rij(i)); + if (fabs(fracdenom) > 1e-10){ + fraction=(r(i)+r(i+1))/fracdenom; + } + Phi2+=atanterm; + ud+=z0l*(yl(i)-yl(i+1))*fraction; + vd+=z0l*(xl(i+1)-xl(i))*fraction; + wd+=wij(i)*fraction; + } + // Doublet potential + Phisd(0)=Phi2/4.0/pi; + // Doublet velocities + ud=ud/4.0/pi; + vd=vd/4.0/pi; + wd=wd/4.0/pi; + + // Transform velocities to global coordinates + uvw(0)=taux(0)*ud+tauy(0)*vd+normal(0)*wd; + uvw(1)=taux(1)*ud+tauy(1)*vd+normal(1)*wd; + uvw(2)=taux(2)*ud+tauy(2)*vd+normal(2)*wd; +} + + + +void Panels::SetKutta() +{ + /* Set up Kutta condition */ + Eigen::MatrixXd Kutta_dummy; + Kutta_dummy.setZero(nPanSpan,2*nPanChord*nPanSpan); + for (size_t i=0; i<nPanSpan; ++i) + { + Kutta_dummy(i,i)=1; + Kutta_dummy(i,(2*nPanChord-1)*nPanSpan+i)=-1; + } + Kutta.setZero(Kutta_dummy.rows(), Kutta_dummy.cols()+(Eigen::MatrixXd::Identity(nPanSpan, nPanSpan).cols())); + Kutta << Kutta_dummy, Eigen::MatrixXd::Identity(nPanSpan, nPanSpan); +} \ No newline at end of file diff --git a/sdpm/src/pPanels.h b/sdpm/src/pPanels.h new file mode 100644 index 0000000000000000000000000000000000000000..736330cf28afda60ab2a5784812da3e01cd6ffb8 --- /dev/null +++ b/sdpm/src/pPanels.h @@ -0,0 +1,135 @@ +#ifndef PPANELS_H +#define PPANELS_H + +#include "sdpm.h" +#include <vector> +#include <Eigen/Dense> + +namespace sdpm +{ + +class DART_API Panels +{ + +private: + +public: + double c0 = 1; /* Root chord (m) */ + double lambda = 1; /* Taper ratio (-) */ + double epsilon = 0; /* Twist angle (rad) */ + double LambdaC4 = 0; /* Sweep angle at 1/4 chord (rad) */ + double b = 1; /* Span (m) */ + double dihedral = 0; /* Dihedral angle (rad) */ + double ax = 0; /* Axis around which twist and taper are defined */ + + double beta; + double Surface; + + size_t nPanChord, nPanSpan; + + /* Bound panel corner point matrices */ + Eigen::MatrixXd Xp; // Size (2m+1, n) + Eigen::MatrixXd Yp; + Eigen::MatrixXd Zp; + + /* Compressibility scaling */ + Eigen::MatrixXd Xp0; // =Xp; + Eigen::MatrixXd Yp0; // =Yp; + Eigen::MatrixXd Zp0; // =Zp; + + /* Control points */ + Eigen::MatrixXd Xc; // =zeros(2*m,n); + Eigen::MatrixXd Yc; + Eigen::MatrixXd Zc; + Eigen::MatrixXd nx; + Eigen::MatrixXd ny; + Eigen::MatrixXd nz; + Eigen::MatrixXd tauxx; + Eigen::MatrixXd tauxy; + Eigen::MatrixXd tauxz; + Eigen::MatrixXd tauyx; + Eigen::MatrixXd tauyy; + Eigen::MatrixXd tauyz; + + Eigen::MatrixXd Xc0; + Eigen::MatrixXd Yc0; + Eigen::MatrixXd Zc0; + + Eigen::MatrixXd s0; + Eigen::MatrixXd cpln; + + /* Surface */ + Eigen::MatrixXd s; + + /* Wake */ + Eigen::MatrixXd Xw; + Eigen::MatrixXd Yw; + Eigen::MatrixXd Zw; + + /* Wake */ + Eigen::MatrixXd MAw; // (mw, n) + Eigen::MatrixXd Xcw; + Eigen::MatrixXd Ycw; + Eigen::MatrixXd Zcw; + Eigen::MatrixXd nxw; + Eigen::MatrixXd nyw; + Eigen::MatrixXd nzw; + Eigen::MatrixXd tauxxw; + Eigen::MatrixXd tauxyw; + Eigen::MatrixXd tauxzw; + Eigen::MatrixXd tauyxw; + Eigen::MatrixXd tauyyw; + Eigen::MatrixXd tauyzw; + Eigen::MatrixXd cp; // (2mw, n) + + /* Normal vectors of compressible geometry panels */ + Eigen::MatrixXd nx0; + Eigen::MatrixXd ny0; + Eigen::MatrixXd nz0; + + /* Influence coefficients */ + + /* Sources */ + Eigen::MatrixXd AN; + Eigen::MatrixXd Au; + Eigen::MatrixXd Av; + Eigen::MatrixXd Aw; + /* Doublets */ + Eigen::MatrixXd BN; + Eigen::MatrixXd Bu; + Eigen::MatrixXd Bv; + Eigen::MatrixXd Bw; + + /* Wake Doublets only */ + Eigen::MatrixXd CN; + Eigen::MatrixXd Cu; + Eigen::MatrixXd Cv; + Eigen::MatrixXd Cw; + + Eigen::MatrixXd Kutta; + + Panels(size_t nPanChord); + + //void CreateWake(double U, double V, double W, double dt); + void ComputeInfluenceCoeffs_wing(); + void ComputeInfluenceCoeffs_wake(unsigned long it); + + void sdpanel_wing(Eigen::RowVector2d &Phisd, Eigen::RowVectorXd &uvw, double x0, double y0, double z0, Eigen::RowVectorXd x, Eigen::RowVectorXd y, Eigen::RowVectorXd z, double xcp, double ycp, double zcp, + Eigen::RowVector3d normal, Eigen::RowVector3d taux, Eigen::RowVector3d tauy); + + void sdpanel_wake(Eigen::RowVectorXd &Phisd, Eigen::RowVectorXd &uvw,double x0, double y0, double z0, Eigen::RowVectorXd x, Eigen::RowVectorXd y, Eigen::RowVectorXd z, double xcp, double ycp, double zcp, + Eigen::RowVector3d normal, Eigen::RowVector3d taux, Eigen::RowVector3d tauy); + + void WakeControlPoints(unsigned long it); + + + void SetKutta(); + + + double Getc0(){return c0;}; + + void CreateWing(); + +}; +} // namespace dart +#endif //PPANELS_H diff --git a/sdpm/src/pSDSolver.cpp b/sdpm/src/pSDSolver.cpp new file mode 100644 index 0000000000000000000000000000000000000000..721fc449736eb65f33348697a18a8887193c6211 --- /dev/null +++ b/sdpm/src/pSDSolver.cpp @@ -0,0 +1,770 @@ +#include "pSDSolver.h" +#include "pPanels.h" +#include <iostream> +#include <vector> +#include <cmath> + +using namespace sdpm; + +SDSolver::SDSolver(Panels *_pan, double _alpha, double _airspeed, unsigned long _maxIt) +{ + pan = _pan; + fs_alpha = _alpha; + fs_airspeed = _airspeed; + maxIt = _maxIt; +} + +void SDSolver::Run() +{ + + int R = 1; /* Wake type */ + + Eigen::Vector3d fs_velocity; + + fs_velocity(0) = fs_airspeed * std::cos(fs_alpha); + fs_velocity(1) = 0; + fs_velocity(2) = fs_airspeed * std::sin(fs_alpha); + + double dt = pan->c0/pan->nPanChord/fs_velocity(0); + + pan->Xw.setZero(maxIt+1, pan->nPanSpan+1); + pan->Yw.setZero(maxIt+1, pan->nPanSpan+1); + pan->Zw.setZero(maxIt+1, pan->nPanSpan+1); + + Eigen::MatrixXd MAw = Eigen::MatrixXd::Zero(maxIt, pan->nPanSpan); + pan->Xcw.setZero(maxIt, pan->nPanSpan); + pan->Ycw.setZero(maxIt, pan->nPanSpan); + pan->Zcw.setZero(maxIt, pan->nPanSpan); + pan->nxw.setZero(maxIt, pan->nPanSpan); + pan->nyw.setZero(maxIt, pan->nPanSpan); + pan->nzw.setZero(maxIt, pan->nPanSpan); + pan->tauxxw.setZero(maxIt, pan->nPanSpan); + pan->tauxyw.setZero(maxIt, pan->nPanSpan); + pan->tauxzw.setZero(maxIt, pan->nPanSpan); + pan->tauyxw.setZero(maxIt, pan->nPanSpan); + pan->tauyyw.setZero(maxIt, pan->nPanSpan); + pan->tauyzw.setZero(maxIt, pan->nPanSpan); + + pan->ComputeInfluenceCoeffs_wing(); + + pan->Xp0 = pan->Xp; + pan->Yp0 = pan->Yp; + pan->Zp0 = pan->Zp; + + /* std::cout << " xp yp zp " << std::endl; + std::cout << pan->Xp << std::endl; + std::cout << pan->Yp << std::endl; + std::cout << pan->Zp << std::endl; + + std::cout << " xc yc zc " << std::endl; + std::cout << pan->Xc << std::endl; + std::cout << pan->Yc << std::endl; + std::cout << pan->Zc << std::endl; */ + + /* Calculate derivative of doublet strength in the chordwise direction */ + /* dX */ + Eigen::MatrixXd dXm1 = (pan->Xc.row(1)-pan->Xc.row(0)); + Eigen::MatrixXd dXm2 = (pan->Xc.block(2,0,2*pan->nPanChord,pan->Xc.cols()) - pan->Xc.block(0,0,2*pan->nPanChord-2,pan->Xc.cols())); + Eigen::MatrixXd dXm3 = (pan->Xc.row(2*pan->nPanChord-1)-pan->Xc.row(2*pan->nPanChord-2)); + + /* Vertical concatenation */ + Eigen::MatrixXd dXm(dXm1.rows()+dXm2.rows()+dXm3.rows(), dXm1.cols()); + dXm << dXm1, + dXm2, + dXm3; + + /* dY */ + Eigen::MatrixXd dYm1 = (pan->Yc.row(1)-pan->Yc.row(0)); + Eigen::MatrixXd dYm2 = (pan->Yc.block(2,0,2*pan->nPanChord,pan->Yc.cols()) - pan->Yc.block(0,0,2*pan->nPanChord-2,pan->Yc.cols())); + Eigen::MatrixXd dYm3 = (pan->Yc.row(2*pan->nPanChord-1)-pan->Yc.row(2*pan->nPanChord-2)); + + /* Vertical concatenation */ + Eigen::MatrixXd dYm(dYm1.rows()+dYm2.rows()+dYm3.rows(), dYm1.cols()); + dYm << dYm1, + dYm2, + dYm3; + + /* dZ */ + Eigen::MatrixXd dZm1 = (pan->Zc.row(1)-pan->Zc.row(0)); + Eigen::MatrixXd dZm2 = (pan->Zc.block(2,0,2*pan->nPanChord,pan->Zc.cols()) - pan->Zc.block(0,0,2*pan->nPanChord-2,pan->Zc.cols())); + Eigen::MatrixXd dZm3 = (pan->Zc.row(2*pan->nPanChord-1)-pan->Zc.row(2*pan->nPanChord-2)); + + /* Vertical concatenation */ + Eigen::MatrixXd dZm(dZm1.rows()+dZm2.rows()+dZm3.rows(), dZm1.cols()); + dZm << dZm1, + dZm2, + dZm3; + + Eigen::MatrixXd sm = (dXm.array()*dXm.array() + dYm.array()*dYm.array() + dZm.array()).sqrt(); + + /* Chordwise tangent vector */ + Eigen::MatrixXd tmx = dXm.array()/sm.array(); + Eigen::MatrixXd tmy = dYm.array()/sm.array(); + Eigen::MatrixXd tmz = dZm.array()/sm.array(); + + /* std::cout << " tm " << std::endl; + std::cout << tmx << std::endl; + std::cout << tmy << std::endl; + std::cout << tmz << std::endl; */ + + + Eigen::MatrixXd dXn; + Eigen::MatrixXd dYn; + Eigen::MatrixXd dZn; + + if (pan->nPanSpan > 2) + { + /* Calculate derivative of doublet strength in the spanwise direction */ + /* dX */ + Eigen::MatrixXd dXn1 = (pan->Xc.col(1)-pan->Xc.col(0)); + Eigen::MatrixXd dXn2 = (pan->Xc.block(0,2,2*pan->nPanChord,pan->nPanSpan) - pan->Xc.block(0,0,2*pan->nPanChord,pan->nPanSpan-2)); + Eigen::MatrixXd dXn3 = (pan->Xc.col(pan->nPanSpan-1)-pan->Xc.col(pan->nPanSpan-2)); + + /* Horizontal concatenation */ + dXn.resize(dXn1.rows(), dXn1.cols()+dXn2.cols()+dXn3.cols()); + dXn << dXn1, dXn2, dXn3; + + /* dY */ + Eigen::MatrixXd dYn1 = (pan->Yc.col(1)-pan->Yc.col(0)); + Eigen::MatrixXd dYn2 = (pan->Yc.block(0,2,2*pan->nPanChord,pan->nPanSpan) - pan->Yc.block(0,0,2*pan->nPanChord,pan->nPanSpan-2)); + Eigen::MatrixXd dYn3 = (pan->Yc.col(pan->nPanSpan-1)-pan->Yc.col(pan->nPanSpan-2)); + + /* Horizontal concatenation */ + dYn.resize(dYn1.rows(), dYn1.cols()+dYn2.cols()+dYn3.cols()); + dYn << dYn1, dYn2, dYn3; + + /* dZ */ + Eigen::MatrixXd dZn1 = (pan->Zc.col(1)-pan->Zc.col(0)); + Eigen::MatrixXd dZn2 = (pan->Zc.block(0,2,2*pan->nPanChord,pan->nPanSpan) - pan->Zc.block(0,0,2*pan->nPanChord,pan->nPanSpan-2)); + Eigen::MatrixXd dZn3 = (pan->Zc.col(pan->nPanSpan-1)-pan->Zc.col(pan->nPanSpan-2)); + + /* Horizontal concatenation */ + dZn.resize(dZn1.rows(), dZn1.cols()+dZn2.cols()+dZn3.cols()); + dZn << dZn1, dZn2, dZn3; + + } + else if (pan->nPanSpan == 2){ + + /* Calculate derivative of doublet strength in the spanwise direction */ + /* dX */ + Eigen::MatrixXd dXn1 = (pan->Xc.col(1)-pan->Xc.col(0)); + + /* Horizontal concatenation */ + dXn.resize(dXn1.rows(), dXn1.cols()+dXn1.cols()); + dXn << dXn1, dXn1; + + /* dY */ + Eigen::MatrixXd dYn1 = (pan->Yc.col(1)-pan->Yc.col(0)); + + /* Horizontal concatenation */ + dYn.resize(dYn1.rows(), dYn1.cols()+dYn1.cols()); + dYn << dYn1, dYn1; + + /* dZ */ + Eigen::MatrixXd dZn1 = (pan->Zc.col(1)-pan->Zc.col(0)); + + /* Horizontal concatenation */ + dZn.resize(dZn1.rows(), dZn1.cols()+dZn1.cols()); + dZn << dZn1, dZn1; + + } + else{ + throw; + } + + Eigen::MatrixXd sn = (dXn.array()*dXn.array() + dYn.array()*dYn.array() + dZn.array()).sqrt(); + + /* std::cout << " dxm dym dzm " << std::endl; + std::cout << dXm << std::endl; + std::cout << dYm << std::endl; + std::cout << dZm << std::endl; + + std::cout << " dxn dyn dzn " << std::endl; + std::cout << dXn << std::endl; + std::cout << dYn << std::endl; + std::cout << dZn << std::endl; */ + + + /* Calculate spanwise tangent vector */ + + Eigen::MatrixXd tnx = dXn.array()/sn.array(); + Eigen::MatrixXd tny = dYn.array()/sn.array(); + Eigen::MatrixXd tnz = dZn.array()/sn.array(); + + /* std::cout << " tnx tny tnz " << std::endl; + std::cout << tnx << std::endl; + std::cout << tny << std::endl; + std::cout << tnz << std::endl; */ + + /* Calculate source strengths */ + + Eigen::MatrixXd SA = -(fs_velocity[0]*pan->nx + fs_velocity[1]*pan->ny + fs_velocity[2]*pan->nz); + Eigen::MatrixXd dum = SA.transpose(); + Eigen::MatrixXd sigma = dum.reshaped(2*pan->nPanSpan*pan->nPanChord,1); + + /* std::cout << " SA sigma " << std::endl; + std::cout << SA << std::endl; + std::cout << sigma << std::endl; */ + + /* Solution at zero time */ + + Eigen::MatrixXd LHS = pan->BN; + Eigen::MatrixXd RHS = -pan->AN * sigma; + Eigen::VectorXd Sol = LHS.partialPivLu().solve(RHS); + + Eigen::MatrixXd Phi0 = Sol.reshaped(pan->nPanSpan, 2*pan->nPanChord).transpose(); + + /* std::cout << "Phi0 " << Phi0 << std::endl; */ + + /* First wake row */ + pan->Xw.row(0) = pan->Xp.row(2*pan->nPanChord); + pan->Yw.row(0) = pan->Yp.row(2*pan->nPanChord); + pan->Zw.row(0) = pan->Zp.row(2*pan->nPanChord); + + CL.setZero(maxIt); + CD.setZero(maxIt); + CY.setZero(maxIt); + + std::vector<Eigen::MatrixXd> Phi(maxIt); + + unsigned long it = 1; + + while(it < maxIt){ + + std::cout << it << std::endl; + + /* Propagate wake */ + Eigen::MatrixXd uwp = Eigen::MatrixXd::Zero(it-1, pan->nPanSpan + 1); + Eigen::MatrixXd vwp = Eigen::MatrixXd::Zero(it-1, pan->nPanSpan + 1); + Eigen::MatrixXd wwp = Eigen::MatrixXd::Zero(it-1, pan->nPanSpan + 1); + + Eigen::MatrixXd dum0(1+uwp.rows(), uwp.cols()); + dum0 << Eigen::MatrixXd::Zero(1,pan->nPanSpan+1), + uwp; + + pan->Xw.block(1,0,it,pan->Xw.cols()) = pan->Xw.block(0,0,it-1,pan->Xw.cols()) + (Eigen::MatrixXd::Constant(dum0.rows(), dum0.cols(), fs_velocity(0)) + dum0)*dt; + + Eigen::MatrixXd dum1(1+vwp.rows(), vwp.cols()); + dum1 << Eigen::MatrixXd::Zero(1,pan->nPanSpan+1), + vwp; + pan->Yw.block(1,0,it,pan->Yw.cols()) = pan->Yw.block(0,0,it-1,pan->Yw.cols()) + (Eigen::MatrixXd::Constant(dum1.rows(), dum1.cols(), fs_velocity(1)) + dum1)*dt; + + Eigen::MatrixXd dum2(1+uwp.rows(), uwp.cols()); + dum2 << Eigen::MatrixXd::Zero(1,pan->nPanSpan+1), + wwp; + pan->Zw.block(1,0,it,pan->Zw.cols()) = pan->Zw.block(0,0,it-1,pan->Zw.cols()) + (Eigen::MatrixXd::Constant(dum2.rows(), dum2.cols(), fs_velocity(2)) + dum2)*dt; + + if (it > 1){ + MAw.block(1,0,it ,MAw.cols()) = MAw.block(0,0,it-1,MAw.cols()); + } + + pan->Xw.row(0) = pan->Xp.row(2*pan->nPanChord); + pan->Yw.row(0) = pan->Yp.row(2*pan->nPanChord); + pan->Zw.row(0) = pan->Zp.row(2*pan->nPanChord); + + /* Calculate wake control points */ + + pan->WakeControlPoints(it); + + /* Calculate wake influence coefficients */ + + pan->ComputeInfluenceCoeffs_wake(it); + + /* Set up Kutta condition */ + + pan->SetKutta(); + + /* Equations */ + + Eigen::MatrixXd LHS; + + /* std::cout << " Here " << std::endl; + std::cout << pan->CN.block(0,0,pan->CN.rows(), pan->nPanSpan) << std::endl; */ + + /* Horizontal concatenation */ + Eigen::MatrixXd LHS_dum1(pan->BN.rows(), pan->BN.cols()+pan->CN.block(0,0,pan->CN.rows(), pan->nPanSpan).cols()); + LHS_dum1 << pan->BN, pan->CN.block(0,0,pan->CN.rows(), pan->nPanSpan); + + /* Vertical concatenation */ + LHS.setZero(LHS_dum1.rows()+pan->Kutta.rows(), LHS_dum1.cols()); + LHS << LHS_dum1, + pan->Kutta; + + Eigen::MatrixXd RHS; + + if (it==1){ + Eigen::MatrixXd RHS_dum1; + RHS_dum1 = -pan->AN*sigma; + + RHS.setZero(RHS_dum1.rows()+Eigen::MatrixXd::Zero(pan->nPanSpan, 1).rows(), RHS_dum1.cols()); + RHS << RHS_dum1, + Eigen::MatrixXd::Zero(pan->nPanSpan, 1); + } + else{ + + Eigen::MatrixXd RHS_dum1; + RHS_dum1 = -pan->AN*sigma - pan->CN.block(0,pan->nPanSpan, pan->CN.rows(), (it-1)*pan->nPanSpan) * MAw.block(1,0,it-1,MAw.cols()).transpose().reshaped((it-1)*pan->nPanSpan,1); + + RHS.setZero(RHS_dum1.rows()+Eigen::MatrixXd::Zero(pan->nPanSpan, 1).rows(), RHS_dum1.cols()); + RHS << RHS_dum1, + Eigen::MatrixXd::Zero(pan->nPanSpan, 1); + + } + + /* Solve for strength */ + + /* std::cout << " LHS " << std::endl; + std::cout << LHS << std::endl; + + std::cout << " RHS " << std::endl; + std::cout << RHS << std::endl; */ + + Eigen::VectorXd Mu2; + Mu2.setZero(RHS.size()); + Mu2 = LHS.partialPivLu().solve(RHS); + + /* std::cout << " Mu2 " << std::endl; + std::cout << Mu2 << std::endl; */ + + /*std::cout << "mu2" << std::endl; + std::cout << Mu2 << std::endl; */ + + Eigen::MatrixXd MA_dum1 = Mu2.reshaped(pan->nPanSpan, 2*pan->nPanChord+1).transpose(); + + /* std::cout << "madum" << std::endl; + std::cout << MA_dum1 << std::endl; */ + + MAw.row(0) = MA_dum1.row(2*pan->nPanChord); + + /* std::cout << "maw" << std::endl; + std::cout << MAw << std::endl; */ + + Eigen::VectorXd Mu(2*pan->nPanChord*pan->nPanSpan); + + + for (size_t i=0; i<2*pan->nPanChord*pan->nPanSpan; ++i) + { + Mu(i) = Mu2(i); + } + /* std::cout << "mu" << std::endl; + std::cout << Mu << std::endl; */ + + Eigen::MatrixXd MA(2*pan->nPanChord, MA_dum1.cols()); + + for (size_t i=0; i<2*pan->nPanChord; ++i) + { + MA.row(i) = MA_dum1.row(i); + } + + /* std::cout << "ma" << std::endl; + std::cout << MA << std::endl; */ + + Phi[it] = MA; + + /* std::cout << " Phi[it] " << Phi[it] << std::endl; */ + + /* std::cout << " phi it " << std::endl; + std::cout << Phi[it] << std::endl; */ + + /* dMA_chord */ + Eigen::MatrixXd dMA1_chord = (MA.row(1)-MA.row(0)); + Eigen::MatrixXd dMA2_chord = (MA.block(2,0,2*pan->nPanChord-1,MA.cols()) - MA.block(0,0,2*pan->nPanChord-2,MA.cols())); + Eigen::MatrixXd dMA3_chord = (MA.row(2*pan->nPanChord-1)-MA.row(2*pan->nPanChord-2)); + + /* Vertical concatenation */ + Eigen::MatrixXd dMA_chord(dMA1_chord.rows()+dMA2_chord.rows()+dMA3_chord.rows(), dMA1_chord.cols()); + dMA_chord << dMA1_chord, + dMA2_chord, + dMA3_chord; + + Eigen::MatrixXd um = dMA_chord.array()/sm.array(); + + /* dMA_span */ + + Eigen::MatrixXd dMA_span; + + if (pan->nPanSpan > 2){ + Eigen::MatrixXd dMA1_span = (MA.col(1)-MA.col(0)); + Eigen::MatrixXd dMA2_span = (MA.block(0,2,2*pan->nPanChord,pan->nPanSpan) - MA.block(0,0,2*pan->nPanChord,pan->nPanSpan-2)); + Eigen::MatrixXd dMA3_span = (MA.col(pan->nPanSpan-1)-MA.col(pan->nPanSpan-2)); + + /* Horizontal concatenation */ + dMA_span.setZero(dMA1_span.rows(), dMA1_span.cols()+dMA2_span.cols()+dMA3_span.cols()); + dMA_span << dMA1_span, dMA2_span, dMA3_span; + } + else if (pan->nPanSpan == 2){ + Eigen::MatrixXd dMA1_span = (MA.col(1)-MA.col(0)); + + /* Horizontal concatenation */ + dMA_span.setZero(dMA1_span.rows(), dMA1_span.cols()+dMA1_span.cols()); + dMA_span << dMA1_span, dMA1_span; + } + else{ + throw; + } + + Eigen::MatrixXd un = dMA_span.array()/sn.array(); + + /* Calculate velocities on control points in the x,y,z directions + On each control point we project the velocities in the chordwise, + spanwise and normal directions to the x,y,z axes */ + Eigen::MatrixXd uc(2*pan->nPanChord, pan->nPanSpan); + Eigen::MatrixXd vc(2*pan->nPanChord, pan->nPanSpan); + Eigen::MatrixXd wc(2*pan->nPanChord, pan->nPanSpan); + + Eigen::Matrix3d Rmat_sys; + Eigen::Vector3d RHS_sys; + Eigen::VectorXd dummy_sys; + + for (size_t i=0;i<2*pan->nPanChord; ++i) + { + for (size_t j=0; j<pan->nPanSpan; ++j) + { + Rmat_sys(0,0) = tmx(i,j); + Rmat_sys(0,1) = tmy(i,j); + Rmat_sys(0,2) = tmz(i,j); + + Rmat_sys(1,0) = tnx(i,j); + Rmat_sys(1,1) = tny(i,j); + Rmat_sys(1,2) = tnz(i,j); + + Rmat_sys(2,0) = pan->nx(i,j); + Rmat_sys(2,1) = pan->ny(i,j); + Rmat_sys(2,2) = pan->nz(i,j); + + RHS_sys(0) = um(i,j); + RHS_sys(1) = un(i,j); + RHS_sys(2) = SA(i,j); + + dummy_sys = Rmat_sys.partialPivLu().solve(RHS_sys); + uc(i,j)=dummy_sys(0); + vc(i,j)=dummy_sys(1); + wc(i,j)=dummy_sys(2); + } + } + + uc = Eigen::MatrixXd::Constant(uc.rows(), uc.cols(), fs_velocity(0)) + uc; + vc = Eigen::MatrixXd::Constant(vc.rows(), vc.cols(), fs_velocity(1)) + vc; + wc = Eigen::MatrixXd::Constant(wc.rows(), wc.cols(), fs_velocity(2)) + wc; + + /* Calculate presssure coefficient */ + Eigen::MatrixXd dPhidt; + if (it==1){ + Eigen::Map<Eigen::VectorXd> Phi1Flatten(Phi[1].data(),Phi[1].size()); + Eigen::Map<Eigen::VectorXd> Phi0Flatten(Phi0.data(),Phi0.size()); + dPhidt = (Phi1Flatten-Phi0Flatten)/dt; + } + else{ + Eigen::Map<Eigen::VectorXd> Phi1Flatten(Phi[it].data(),Phi[it].size()); + Eigen::Map<Eigen::VectorXd> Phi0Flatten(Phi[it-1].data(),Phi[it-1].size()); + dPhidt = (Phi1Flatten - Phi0Flatten)/dt; + } + + Eigen::MatrixXd cp_dum = (uc.array()*uc.array() + vc.array()*vc.array() + wc.array()*wc.array())*1/fs_airspeed/fs_airspeed - 2*dPhidt.array()*1/fs_airspeed/fs_airspeed; + cp = Eigen::MatrixXd::Constant(uc.rows(), uc.cols(), 1) - cp_dum; + + + /* Forces on panels */ + + std::cout << "cp" << std::endl; + std::cout << cp << std::endl; + std::cout << "pan->s" << std::endl; + std::cout << pan->s << std::endl; + std::cout << "pan->nx" << std::endl; + std::cout << pan->nx << std::endl; + std::cout << "pan->Surface" << std::endl; + std::cout << pan->Surface << std::endl; + + Eigen::MatrixXd fx = -cp.array()*pan->s.array()*pan->nx.array()/pan->Surface; + Eigen::MatrixXd fy = -cp.array()*pan->s.array()*pan->nx.array()/pan->Surface; + Eigen::MatrixXd fz = -cp.array()*pan->s.array()*pan->nx.array()/pan->Surface; + + std::cout << fx << std::endl; + std::cout << fy << std::endl; + std::cout << fz << std::endl; + + double Fx = fx.sum(); + //double Fy = fy.sum(); + double Fz = fz.sum(); + + if (R>0){ + CL(it) = Fz; + CD(it) = Fx; + } + else{ + CL(it) = Fz-Fx*fs_alpha; + CD(it) = Fz*fs_alpha+Fx; + } + std::cout << " CL = " << CL(it) << std::endl; + it++; + + } +} + + + // int nChords = 100; + // double dt = nChords * pan->Getc0() / fs_velocity[0]; + + // /* Source strength */ + + // Eigen::MatrixXd SA = -(fs_velocity[0]*pan->nx/fs_beta + fs_velocity[1]*pan->ny + fs_velocity[2]*pan->nz); + // Eigen::MatrixXd dum = SA.transpose(); + // Eigen::MatrixXd sigma = dum.reshaped(2*pan->nPanSpan*pan->nPanChord,1); + + // pan->CreateWake(fs_velocity[0], fs_velocity[1], fs_velocity[2], fs_beta, dt); + // std::cout << "Wake created." << std::endl; + + // pan->ComputeInfluenceCoeffs_wing(); + // pan->ComputeInfluenceCoeffs_wake(); + // std::cout << "Computed influence coefficients." << std::endl; + + // pan->SetKutta(); + // std::cout << "Imposed Kutta condition." << std::endl; + + // /* Set up Dirichlet boundary condition */ + + // /* Horizontal concatenation */ + // Eigen::MatrixXd LHS_dum1(pan->BN.rows(), pan->BN.cols()+pan->CN.cols()); + // LHS_dum1 << pan->BN, pan->CN; + + // /* Vertical concatenation */ + // Eigen::MatrixXd LHS(LHS_dum1.rows()+pan->Kutta.rows(), LHS_dum1.cols()); + // LHS << LHS_dum1, + // pan->Kutta; + + // Eigen::MatrixXd RHS_dum1; + // RHS_dum1 = -pan->AN*sigma; + + // Eigen::MatrixXd RHS(RHS_dum1.rows()+Eigen::MatrixXd::Zero(pan->nPanSpan, 1).rows(), RHS_dum1.cols()); + // RHS << RHS_dum1, + // Eigen::MatrixXd::Zero(pan->nPanSpan, 1); + + // /* Solve for strength */ + // Eigen::VectorXd Mu = LHS.partialPivLu().solve(RHS); + + // Eigen::MatrixXd MA_dum1; + // MA_dum1 = Mu.reshaped(pan->nPanSpan, 2*pan->nPanChord+1).transpose(); + + // /* Wake doublet strengths */ + + // Eigen::RowVectorXd Mw = MA_dum1.row(MA_dum1.rows()-1); // Last row of MA_dum1 + + // Eigen::VectorXd Mu2(2*pan->nPanChord*pan->nPanSpan); + + // for (size_t i=0; i<2*pan->nPanChord*pan->nPanSpan; ++i) + // { + // Mu2.row(i) = Mu.row(i); + // } + + // Eigen::MatrixXd MA(2*pan->nPanChord, MA_dum1.cols()); + + // for (size_t i=0; i<2*pan->nPanChord; ++i) + // { + // MA.row(i) = MA_dum1.row(i); + // } + + // /* Calculate derivative of doublet strength in the chordwise direction */ + // /* dX */ + // Eigen::MatrixXd dXc1_chord = (pan->Xc.row(1)-pan->Xc.row(0)); + // Eigen::MatrixXd dXc2_chord = (pan->Xc.block(2,0,2*pan->nPanChord,pan->Xc.cols()) - pan->Xc.block(0,0,2*pan->nPanChord-2,pan->Xc.cols())); + // Eigen::MatrixXd dXc3_chord = (pan->Xc.row(2*pan->nPanChord-1)-pan->Xc.row(2*pan->nPanChord-2)); + + // /* Vertical concatenation */ + // Eigen::MatrixXd dXc_chord(dXc1_chord.rows()+dXc2_chord.rows()+dXc3_chord.rows(), dXc1_chord.cols()); + // dXc_chord << dXc1_chord, + // dXc2_chord, + // dXc3_chord; + + // /* dY */ + // Eigen::MatrixXd dYc1_chord= (pan->Yc.row(1)-pan->Yc.row(0)); + // Eigen::MatrixXd dYc2_chord= (pan->Yc.block(2,0,2*pan->nPanChord,pan->Yc.cols()) - pan->Yc.block(0,0,2*pan->nPanChord-2,pan->Yc.cols())); + // Eigen::MatrixXd dYc3_chord = (pan->Yc.row(2*pan->nPanChord-1)-pan->Yc.row(2*pan->nPanChord-2)); + + // /* Vertical concatenation */ + // Eigen::MatrixXd dYc_chord(dYc1_chord.rows()+dYc2_chord.rows()+dYc3_chord.rows(), dYc1_chord.cols()); + // dYc_chord << dYc1_chord, + // dYc2_chord, + // dYc3_chord; + + // /* dZ */ + // Eigen::MatrixXd dZc1_chord = (pan->Zc.row(1)-pan->Zc.row(0)); + // Eigen::MatrixXd dZc2_chord = (pan->Zc.block(2,0,2*pan->nPanChord,pan->Zc.cols()) - pan->Zc.block(0,0,2*pan->nPanChord-2,pan->Zc.cols())); + // Eigen::MatrixXd dZc3_chord = (pan->Zc.row(2*pan->nPanChord-1)-pan->Zc.row(2*pan->nPanChord-2)); + + // /* Vertical concatenation */ + // Eigen::MatrixXd dZc_chord(dZc1_chord.rows()+dZc2_chord.rows()+dZc3_chord.rows(), dZc1_chord.cols()); + // dZc_chord << dZc1_chord, + // dZc2_chord, + // dZc3_chord; + + // /* dMA_chord */ + // Eigen::MatrixXd dMA1_chord = (MA.row(1)-MA.row(0)); + // Eigen::MatrixXd dMA2_chord = (MA.block(2,0,2*pan->nPanChord,MA.cols()) - MA.block(0,0,2*pan->nPanChord-2,MA.cols())); + // Eigen::MatrixXd dMA3_chord = (MA.row(2*pan->nPanChord-1)-MA.row(2*pan->nPanChord-2)); + + // /* Vertical concatenation */ + // Eigen::MatrixXd dMA_chord(dMA1_chord.rows()+dMA2_chord.rows()+dMA3_chord.rows(), dMA1_chord.cols()); + // dMA_chord << dMA1_chord, + // dMA2_chord, + // dMA3_chord; + + // /* Calculate chordwise tangent vectors */ + // /* .array() member of MatrixXd allows the structure to be treated as ArrayXd for the operation. + // This allows product element by element instead of the classic matrix product of MatrixXd (aliasing is present for ArrayXd*ArrayXd)*/ + // Eigen::MatrixXd sc_chord = (dXc_chord.array()*dXc_chord.array()+dYc_chord.array()*dYc_chord.array()+dZc_chord.array()*dZc_chord.array()).sqrt(); + + // Eigen::MatrixXd tmx_chord = dXc_chord.array()/sc_chord.array(); + // Eigen::MatrixXd tmy_chord = dYc_chord.array()/sc_chord.array(); + // Eigen::MatrixXd tmz_chord = dZc_chord.array()/sc_chord.array(); + // /* Calculate the velocity in the chordwise direction */ + // Eigen::MatrixXd um = dMA_chord.array()/sc_chord.array(); + + + // /* Calculate derivative of doublet strength in the spanwise direction */ + // /* dX */ + // Eigen::MatrixXd dXc1_span = (pan->Xc.col(1)-pan->Xc.col(0)); + // Eigen::MatrixXd dXc2_span = (pan->Xc.block(0,2,2*pan->nPanChord,pan->nPanSpan) - pan->Xc.block(0,0,2*pan->nPanChord,pan->nPanSpan-2)); + // Eigen::MatrixXd dXc3_span = (pan->Xc.col(pan->nPanSpan-1)-pan->Xc.col(pan->nPanSpan-2)); + + // /* Horizontal concatenation */ + // Eigen::MatrixXd dXc_span(dXc1_span.rows(), dXc1_span.cols()+dXc2_span.cols()+dXc3_span.cols()); + // dXc_span << dXc1_span, dXc2_span, dXc3_span; + + // /* dY */ + // Eigen::MatrixXd dYc1_span = (pan->Yc.col(1)-pan->Yc.col(0)); + // Eigen::MatrixXd dYc2_span = (pan->Yc.block(0,2,2*pan->nPanChord,pan->nPanSpan) - pan->Yc.block(0,0,2*pan->nPanChord,pan->nPanSpan-2)); + // Eigen::MatrixXd dYc3_span = (pan->Yc.col(pan->nPanSpan-1)-pan->Yc.col(pan->nPanSpan-2)); + + // /* Horizontal concatenation */ + // Eigen::MatrixXd dYc_span(dYc1_span.rows(), dYc1_span.cols()+dYc2_span.cols()+dYc3_span.cols()); + // dYc_span << dYc1_span, dYc2_span, dYc3_span; + + // /* dZ */ + // Eigen::MatrixXd dZc1_span = (pan->Zc.col(1)-pan->Zc.col(0)); + // Eigen::MatrixXd dZc2_span = (pan->Zc.block(0,2,2*pan->nPanChord,pan->nPanSpan) - pan->Zc.block(0,0,2*pan->nPanChord,pan->nPanSpan-2)); + // Eigen::MatrixXd dZc3_span = (pan->Zc.col(pan->nPanSpan-1)-pan->Zc.col(pan->nPanSpan-2)); + + // /* Horizontal concatenation */ + // Eigen::MatrixXd dZc_span(dZc1_span.rows(), dZc1_span.cols()+dZc2_span.cols()+dZc3_span.cols()); + // dZc_span << dZc1_span, dZc2_span, dZc3_span; + + // /* dMA_span */ + // Eigen::MatrixXd dMA1_span = (MA.col(1)-MA.col(0)); + // Eigen::MatrixXd dMA2_span = (MA.block(0,2,2*pan->nPanChord,pan->nPanSpan) - MA.block(0,0,2*pan->nPanChord,pan->nPanSpan-2)); + // Eigen::MatrixXd dMA3_span = (MA.col(pan->nPanSpan-1)-MA.col(pan->nPanSpan-2)); + + // /* Horizontal concatenation */ + // Eigen::MatrixXd dMA_span(dMA1_span.rows(), dMA1_span.cols()+dMA2_span.cols()+dMA3_span.cols()); + // dMA_span << dMA1_span, dMA2_span, dMA3_span; + + // /* Calculate spanwise tangent vectors */ + // /* .array() member of MatrixXd allows the structure to be treated as ArrayXd for the operation. + // This allows product element by element instead of the classic matrix product of MatrixXd (aliasing is present for ArrayXd*ArrayXd)*/ + // Eigen::MatrixXd sc_span = (dXc_span.array()*dXc_span.array()+dYc_span.array()*dYc_span.array()+dZc_span.array()*dZc_span.array()).sqrt(); + + // Eigen::MatrixXd tnx_span = dXc_span.array()/sc_span.array(); + // Eigen::MatrixXd tny_span = dYc_span.array()/sc_span.array(); + // Eigen::MatrixXd tnz_span = dZc_span.array()/sc_span.array(); + // /* Calculate the velocity in the chordwise direction */ + // Eigen::MatrixXd un = dMA_span.array()/sc_span.array(); + + // /* Calculate velocities on control points in the x,y,z directions + // On each control point we project the velocities in the chordwise, + // spanwise and normal directions to the x,y,z axes */ + // Eigen::MatrixXd uc(2*pan->nPanChord, pan->nPanSpan); + // Eigen::MatrixXd vc(2*pan->nPanChord, pan->nPanSpan); + // Eigen::MatrixXd wc(2*pan->nPanChord, pan->nPanSpan); + + // Eigen::Matrix3d Rmat_sys; + // Eigen::Vector3d RHS_sys; + // Eigen::VectorXd dummy_sys; + + // for (size_t i=0;i<2*pan->nPanChord; ++i) + // { + // for (size_t j=0; j<pan->nPanSpan; ++j) + // { + // Rmat_sys(0,0) = tmx_chord(i,j); + // Rmat_sys(0,1) = tmy_chord(i,j); + // Rmat_sys(0,2) = tmz_chord(i,j); + + // Rmat_sys(1,0) = tnx_span(i,j); + // Rmat_sys(1,1) = tny_span(i,j); + // Rmat_sys(1,2) = tnz_span(i,j); + + // Rmat_sys(2,0) = pan->nx(i,j); + // Rmat_sys(2,1) = pan->ny(i,j); + // Rmat_sys(2,2) = pan->nz(i,j); + + // RHS_sys(0) = um(i,j); + // RHS_sys(1) = un(i,j); + // RHS_sys(2) = SA(i,j); // or SA0? + + // dummy_sys = Rmat_sys.partialPivLu().solve(RHS_sys); + // uc(i,j)=dummy_sys(0); + // vc(i,j)=dummy_sys(1); + // wc(i,j)=dummy_sys(2); + // } + // } + + // /* Scale velocity to compressible space */ + // uc/=fs_beta; + // uc+=Eigen::MatrixXd::Constant(uc.rows(),uc.cols(),fs_velocity(0)); + // vc+=Eigen::MatrixXd::Constant(vc.rows(),vc.cols(),fs_velocity(1)); + // wc+=Eigen::MatrixXd::Constant(wc.rows(),wc.cols(),fs_velocity(2)); + + // std::cout << " uc " << uc << std::endl; + // std::cout << " vc " << vc << std::endl; + // std::cout << " wc " << wc << std::endl; + + + // /* Calculate pressure coefficient using second order relationship */ + // Eigen::MatrixXd bracket = Eigen::MatrixXd::Constant(uc.rows(),uc.cols(),1/2).array()*(uc.array()*uc.array()+vc.array()*vc.array()+wc.array()*wc.array()) - Eigen::MatrixXd::Constant(uc.rows(),uc.cols(),1/2*fs_airspeed*fs_airspeed).array(); + + // std::cout << "brack " << bracket << std::endl; + + // Eigen::MatrixXd cp=(-bracket.array() + Eigen::MatrixXd::Constant(bracket.rows(), bracket.cols(),1/2/(fs_asound*fs_asound)).array() * bracket.array() * bracket.array()) * Eigen::MatrixXd::Constant(bracket.rows(), bracket.cols(),2/(fs_airspeed*fs_airspeed)).array(); + // std::cout << " cp " << cp << std::endl; + + // % Calculate total velocity + // Vtot2=uc.^2+vc.^2+wc.^2; + + // % Calculate maximum velocity (giving Mach=1); + // Vmax=Q*sqrt(1+2/((gama-1)*Mach^2)); + // % Calculate local speed of sound + // asound_local=asound*sqrt(1-(gama-1)/2*Mach^2*(Vtot2/Q^2-1)); + // % Calculate local Mach number + // Mach_local=sqrt(Vtot2)./asound_local; + // % Calculate critical velocity (where local Mach number = 1) + // Vcrit=sqrt((gama-1)/(gama+1))*Vmax; + // iko=find(sqrt(Vtot2) >= Vcrit); + // if ~isempty(iko) + // disp('Warning! Sonic Mach number exceeded') + // super=1; + // end + // supervec(ialpha)=super; + + // % Calculate forces on panels + // fx=-cp.*s0.*nx0/S; + // fy=-cp.*s0.*ny0/S; + // fz=-cp.*s0.*nz0/S; + + // % Calculate total forces on wing in the x,y,z directions + // Fx=sum(sum(fx)); + // Fy=sum(sum(fy)); + // Fy_half=sum(sum(fy(:,n/2+1:n))); + // Fz=sum(sum(fz)); + + // % Calculate lift and drag coefficients + // CL(ialpha)=Fz*cos(alpha)-Fx*sin(alpha); + // CD(ialpha)=Fz*sin(alpha)+Fx*cos(alpha); + // CY(ialpha)=Fy; + // CY_half(ialpha)=Fy_half; + + // % Calculate lift and drag distributions + // dy=Yp(1,2:n+1)-Yp(1,1:n); + // cc=(cvar(2:end)+cvar(1:end-1))/2; + // cfx=S*sum(fx,1)./dy./cc; + // cfy=S*sum(fy,1)./dy./cc; + // cfz=S*sum(fz,1)./dy./cc; + // Cl=cfz*cos(alpha)-cfx*sin(alpha); + // Cd=cfx*cos(alpha)+cfz*sin(alpha); \ No newline at end of file diff --git a/sdpm/src/pSDSolver.h b/sdpm/src/pSDSolver.h new file mode 100644 index 0000000000000000000000000000000000000000..9180461797d056018252e3c4ca140d49a315f457 --- /dev/null +++ b/sdpm/src/pSDSolver.h @@ -0,0 +1,35 @@ +#ifndef PSDSOLVER_H +#define PSDSOLVER_H + +#include "sdpm.h" +#include "pPanels.h" +#include <vector> +#include <string> + +namespace sdpm +{ + +class DART_API SDSolver +{ + +private: + + + +public: + +Panels *pan; +double fs_alpha, fs_Mach, fs_airspeed; +unsigned long maxIt; +Eigen::VectorXd CL; +Eigen::VectorXd CD; +Eigen::VectorXd CY; +Eigen::MatrixXd cp; + +SDSolver(Panels *_pan, double _alpha, double _airspeed, unsigned long _maxIt); +void Run(); + + +}; +} // namespace sdpm +#endif //WSDSolver_H diff --git a/sdpm/src/sdpm.h b/sdpm/src/sdpm.h new file mode 100644 index 0000000000000000000000000000000000000000..c5dc54e405f2404dfcccd3a3b39822fc793d8822 --- /dev/null +++ b/sdpm/src/sdpm.h @@ -0,0 +1,44 @@ +/* + * Copyright 2020 University of Liège + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// global header of the "sdpm" module + +#ifndef sdpm_H +#define sdpm_H + +#if defined(WIN32) +#ifdef sdpm_EXPORTS +#define DART_API __declspec(dllexport) +#else +#define DART_API __declspec(dllimport) +#endif +#else +#define DART_API +#endif + +#include "tbox.h" + +/** + * @brief Namespace for dart module + */ +namespace sdpm +{ +// Viscous +class Panels; +class SDSolver; +} // namespace sdpm + +#endif //SDPM_H diff --git a/sdpm/tests/panels3d.py b/sdpm/tests/panels3d.py new file mode 100644 index 0000000000000000000000000000000000000000..04bb3b13f3538e979c1c7987b1d0819fe1ab58a3 --- /dev/null +++ b/sdpm/tests/panels3d.py @@ -0,0 +1,27 @@ +import sdpm +import math +from matplotlib import pyplot as plt + +def main(): + + alpha = 2.*math.pi/180 + + nPanels = 2 + airspeed = 50 + maxIt = 10 + + wing = sdpm.Panels(nPanels) + wing.CreateWing() + + solver = sdpm.SDSolver(wing, alpha, airspeed, maxIt) + print('Computation started (pyCheck)') + + solver.Run() + + plt.plot(solver.CL) + plt.show() + + print('Computation ended (pyCheck)') + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/vii/_src/viiw.h b/vii/_src/viiw.h index 806068743093274c2a5ba04e883db833fca3158f..0779519f043bd4dbbd87e725d764a15986524687 100644 --- a/vii/_src/viiw.h +++ b/vii/_src/viiw.h @@ -20,5 +20,4 @@ #include "wViscFluxes.h" #include "wClosures.h" #include "wViscMesh.h" -#include "wInvBnd.h" -#include "wCoupler.h" \ No newline at end of file +#include "wInvBnd.h" \ No newline at end of file diff --git a/vii/_src/viiw.i b/vii/_src/viiw.i index 2d788b18118ef354402b03998f6ca3fc4181d2ca..4afee6e1640b86263f53cbc72fbd7a245edcbab1 100644 --- a/vii/_src/viiw.i +++ b/vii/_src/viiw.i @@ -49,5 +49,4 @@ threads="1" %include "wViscFluxes.h" %include "wClosures.h" %include "wViscMesh.h" -%include "wInvBnd.h" -%include "wCoupler.h" \ No newline at end of file +%include "wInvBnd.h" \ No newline at end of file diff --git a/vii/pyVII/DAirfoil.py b/vii/pyVII/DAirfoil.py index e8986c86036c040ebac6860fbd7b67afbeacd81c..70605b55cedbb79d6a893214bd451cb3341ff815 100755 --- a/vii/pyVII/DAirfoil.py +++ b/vii/pyVII/DAirfoil.py @@ -135,6 +135,4 @@ class Airfoil(Boundary): uData = data[0:np.argmax(data[:,0])+1] lData = data[np.argmax(data[:,0])+1:None] lData = np.insert(lData, 0, uData[0,:], axis = 0) #double the stagnation point - print(np.shape(connectListNodes)) - quit() return connectListNodes, connectListElems,[uData, lData] diff --git a/vii/pyVII/vCoupler.py b/vii/pyVII/vCoupler.py index 78d78c9237cb2fe0fd4530c789cf9d240b5a925f..5378573b2824206f1bf556e2d6aee5aa751e8493 100644 --- a/vii/pyVII/vCoupler.py +++ b/vii/pyVII/vCoupler.py @@ -193,8 +193,6 @@ class Coupler: self.fMeshDict, _, _ = GroupConstructor().mergeVectors(dataIn, 0, 1) fMeshDict = self.fMeshDict.copy() if ((len(fMeshDict['locCoord'][:fMeshDict['bNodes'][1]]) != self.nElmUpperPrev) or couplIter==0): - - print('STAG POINT MOVED') # Initialize mesh diff --git a/vii/src/wBLRegion.cpp b/vii/src/wBLRegion.cpp index 0f83eccf4342444ca174461ca471b6967f776a3f..deb501f57579cd604c7e1b73e956b16beaee72d6 100644 --- a/vii/src/wBLRegion.cpp +++ b/vii/src/wBLRegion.cpp @@ -2,12 +2,8 @@ #include "wClosures.h" #include "wViscMesh.h" #include "wInvBnd.h" -#include <iostream> -#include <vector> #include <cmath> - #include <iomanip> -#include <deque> using namespace vii; @@ -35,6 +31,9 @@ BLRegion::~BLRegion() // std::cout << "~BLRegion()\n"; } // end ~BLRegion +/** + * @brief Set mesh in the global frame of reference + */ void BLRegion::SetMesh(std::vector<double> x, std::vector<double> y, std::vector<double> z) @@ -63,6 +62,9 @@ void BLRegion::SetMesh(std::vector<double> x, } } // End SetMesh +/** + * @brief Impose boundary condition at the stagnation point + */ void BLRegion::SetStagBC(double Re) { double dv0 = (invBnd->GetVt(1) - invBnd->GetVt(0)) / (mesh->GetLoc(1) - mesh->GetLoc(0)); @@ -105,6 +107,9 @@ void BLRegion::SetStagBC(double Re) } // End SetStagBC +/** + * @brief Impose boundary condition at the first wake point + */ void BLRegion::SetWakeBC(double Re, std::vector<double> UpperCond, std::vector<double> LowerCond) { if (name!="wake") @@ -145,6 +150,9 @@ void BLRegion::SetWakeBC(double Re, std::vector<double> UpperCond, std::vector<d } } +/** + * @brief Compute blowing velocities at each station + */ void BLRegion::ComputeBlwVel() { DeltaStar[0] = U[0] * U[1]; @@ -157,7 +165,9 @@ void BLRegion::ComputeBlwVel() } } - +/** + * @brief Print solution at a given station + */ void BLRegion::PrintSolution(size_t iPoint) const { std::cout << "Pt " << iPoint << "Reg " << Regime[iPoint] << std::endl; diff --git a/vii/src/wBLRegion.h b/vii/src/wBLRegion.h index b109fdf7ce271c48f47458e8f1199b5f648b7a6d..e1b197966f08d53dca8b32500a931c746e8ca9cb 100644 --- a/vii/src/wBLRegion.h +++ b/vii/src/wBLRegion.h @@ -5,8 +5,6 @@ #include "wClosures.h" #include "wViscMesh.h" #include "wInvBnd.h" -#include <vector> -#include <string> namespace vii { @@ -15,44 +13,44 @@ class DART_API BLRegion { private: - unsigned int const nVar = 5; + unsigned int const nVar = 5; /* Number of variables of the partial differential problem */ /* Transition related variables */ - double nCrit = 9.0; + double nCrit = 9.0; /* Critical amplification factor */ public: - ViscMesh *mesh; - InvBnd *invBnd; - Closures *closSolver; + ViscMesh *mesh; /* Boundary layer mesh */ + InvBnd *invBnd; /* Inviscid quantities at the edge of the boundary layer */ + Closures *closSolver; /* Closure relatrions module */ - std::string name; /* Name of the region */ + std::string name; /* Name of the region */ /* Boundary layer variables */ - std::vector<double> U; /* Solution vector (theta, H, N, ue, Ct) */ - std::vector<double> Ret; /* Reynolds number based on the momentum thickness (theta) */ - std::vector<double> Cd; /* Local dissipation coefficient */ - std::vector<double> Cf; /* Local friction coefficient */ - std::vector<double> Hstar; - std::vector<double> Hstar2; - std::vector<double> Hk; - std::vector<double> Cteq; - std::vector<double> Us; - std::vector<double> Delta; + std::vector<double> U; /* Solution vector (theta, H, N, ue, Ct) */ + std::vector<double> Ret; /* Reynolds number based on the momentum thickness (theta) */ + std::vector<double> Cd; /* Local dissipation coefficient */ + std::vector<double> Cf; /* Local friction coefficient */ + std::vector<double> Hstar; /* Kinetic energy shape parameter (thetaStar/theta) */ + std::vector<double> Hstar2; /* Density shape parameter (deltaStarStar/theta) */ + std::vector<double> Hk; /* Kinematic shape parameter (int(1-u/ue deta)) */ + std::vector<double> Cteq; /* Equilibrium shear stress coefficient (turbulent BL) */ + std::vector<double> Us; /* Equivalent normalized wall slip velocity */ + std::vector<double> Delta; /* Boundary layer thickness */ - std::vector<double> DeltaStar; + std::vector<double> DeltaStar; /* Dispacement thickness (int(1-rho*u/rhoe*ue deta)) */ /* Transition related variables */ - std::vector<int> Regime; - std::vector<double> Blowing; + std::vector<int> Regime; /* Laminar (0) or turbulent (1) regime */ + std::vector<double> Blowing; /* Blowing velocity */ - unsigned int transMarker; - double xtrF; - double xtr; + unsigned int transMarker; /* Marker of the transition location */ + double xtrF; /* Forced transition location */ + double xtr; /* Transition location (=xtrF if forced) */ BLRegion(double _xtrF = -1.0); ~BLRegion(); diff --git a/vii/src/wClosures.cpp b/vii/src/wClosures.cpp index 10b2349952d107b8005be1a4273453f8f58a9a70..49c1aa85bc2c1afb541e995f94a2c26fb4adf61d 100644 --- a/vii/src/wClosures.cpp +++ b/vii/src/wClosures.cpp @@ -1,19 +1,17 @@ #include "wClosures.h" +#include <cmath> #include <iostream> -#include <math.h> -#include <string> -using namespace tbox; using namespace vii; // This is an empty constructor Closures::Closures() {} -Closures::~Closures() -{ - // std::cout << "~Closures()\n"; -} // end ~Closures +Closures::~Closures(){} +/** + * @brief Laminar closure relations + */ std::vector<double> Closures::LaminarClosures(double theta, double H, double Ret, double Me, std::string name) const { @@ -49,7 +47,7 @@ std::vector<double> Closures::LaminarClosures(double theta, double H, double Ret { Hstar = 1.528 + 0.015*Hks*Hks/Hk; } - // Whitfield's minor additional compressibility correction + /* Whitfield's minor additional compressibility correction */ Hstar = (Hstar + 0.028*Me*Me)/(1+0.014*Me*Me); /* Friction coefficient */ @@ -106,6 +104,9 @@ std::vector<double> Closures::LaminarClosures(double theta, double H, double Ret return ClosureVars; } +/** + * @brief Turbulent closure relations + */ std::vector<double> Closures::TurbulentClosures(double theta, double H, double Ct, double Ret, double Me, std::string name) const { /*if (std::isnan(Ret)) diff --git a/vii/src/wDartCoupler.cpp b/vii/src/wDartCoupler.cpp deleted file mode 100644 index cd40af47155f42ede0f8215ba6116422f3968025..0000000000000000000000000000000000000000 --- a/vii/src/wDartCoupler.cpp +++ /dev/null @@ -1,172 +0,0 @@ -#include "wDartCoupler.h" -#include "../../dart/src/wNewton.h" -#include "../../dart/src/wBlowing.h" -#include "wViscSolver.h" - -using namespace vii; - -DartCoupler::DartCoupler(const Newton *_invSolver, ViscSolver *_viscSolver, const std::vector<*Blowing> _blw, unsigned long _nCouplIter = 150, double _tol = 1e-4) -{ - invSolver = _invSolver; - viscSolver = _viscSolver; - blw = _blw; - - maxCouplIter = _nCouplIter; - tol = _tol; - - Initialize(); -} -DartCoupler::~DartCoupler() - -void DartCoupler::Run(){ - double cdPrev = 0.; - double error = 1.; - - unsigned long nIters; - - while (nIters < maxCouplIter){ - - invSolver.run(); - - ImposeInviscidBC(); - - viscSolver.Run(); - - error = (viscSolver.Cdt - cdPrev) / viscSolver.Cdt; - - if (error < tol){ - break; - } - else{ - continue; - } - - cdPrev = viscSolver.Cdt; - - ImposeBlowing(); - - nIters++; - - } - - else{ - std::cout << "Maximum number of " << maxCouplIter << " reached." << std::endl; - } -} -void DartCoupler::ImposeInviscidBC(){ - - for (int iReg=0; iReg < blw.size(); ++iReg){ - - for (auto iNode : blw[iReg]->nodes){ - invSolver->U(iNode->row) - } - } -} - -void DartCoupler::ImposeBlowing() - -void DartCoupler::Initialize(){ - - /* Create connectivity list */ - - std::vector<std::vector<unsigned int>,2> connectListNodes; - std::vector<std::vector<unsigned int>,2> connectListElems; - - for (size_t iReg=0; iReg < blw.size(); ++iReg) - { - connectListNodes(iReg).resize(blw(iReg)->boundary->nodes.size(), 0); - connectListElems(iReg).resize(blw(iReg)->boudnary->tag->elems.size(), 0); - } - - - /* Find stagnation point */ - int idxStag = - - - N1 = np.zeros(self.nN, dtype=int) # Node number - connectListNodes = np.zeros(self.nN, dtype=int) # Index in boundary.nodes - connectListElems = np.zeros(self.nE, dtype=int) # Index in boundary.elems - data = np.zeros((self.boundary.nodes.size(), 10)) - i = 0 - for n in self.boundary.nodes: - data[i,0] = n.no - data[i,1] = n.pos[0] - data[i,2] = n.pos[1] - data[i,3] = n.pos[2] - data[i,4] = self.v[i,0] - data[i,5] = self.v[i,1] - data[i,6] = self.Me[i] - data[i,7] = self.rhoe[i] - data[i,8] = self.deltaStar[i] - data[i,9] = self.xx[i] - i += 1 - # Table containing the element and its nodes - eData = np.zeros((self.nE,3), dtype=int) - for i in range(0, self.nE): - eData[i,0] = self.boundary.tag.elems[i].no - eData[i,1] = self.boundary.tag.elems[i].nodes[0].no - eData[i,2] = self.boundary.tag.elems[i].nodes[1].no - # Find the stagnation point - if couplIter == 0: - self.idxStag = np.argmin(np.sqrt(data[:,4]**2+data[:,5]**2)) - idxStag = self.idxStag - else: - idxStag = self.idxStag - #idxStag = np.argmin(np.sqrt(data[:,4]**2+data[:,5]**2)) - globStag = int(data[idxStag,0]) # position of the stagnation point in boundary.nodes - # Find TE nodes (assuming suction side element is above pressure side element in the y direction) - idxTE = np.where(data[:,1] == np.max(data[:,1]))[0] # TE nodes - idxTEe0 = np.where(np.logical_or(eData[:,1] == data[idxTE[0],0], eData[:,2] == data[idxTE[0],0]))[0] # TE element 1 - idxTEe1 = np.where(np.logical_or(eData[:,1] == data[idxTE[1],0], eData[:,2] == data[idxTE[1],0]))[0] # TE element 2 - ye0 = 0.5 * (data[np.where(data[:,0] == eData[idxTEe0[0],1])[0],2] + data[np.where(data[:,0] == eData[idxTEe0[0],2])[0],2]) # y coordinates of TE element 1 CG - ye1 = 0.5 * (data[np.where(data[:,0] == eData[idxTEe1[0],1])[0],2] + data[np.where(data[:,0] == eData[idxTEe1[0],2])[0],2]) # y coordinates of TE element 2 CG - if ye0 - ye1 > 0: # element 1 containing TE node 1 is above element 2 - upperGlobTE = int(data[idxTE[0],0]) - lowerGlobTE = int(data[idxTE[1],0]) - else: - upperGlobTE = int(data[idxTE[1],0]) - lowerGlobTE = int(data[idxTE[0],0]) - # Connectivity - connectListElems[0] = np.where(eData[:,1] == globStag)[0] - N1[0] = eData[connectListElems[0],1] # number of the stag node elems.nodes -> globStag - connectListNodes[0] = np.where(data[:,0] == N1[0])[0] - i = 1 - upperTE = 0 - lowerTE = 0 - # Sort the suction part - while upperTE == 0: - N1[i] = eData[connectListElems[i-1],2] # Second node of the element - connectListElems[i] = np.where(eData[:,1] == N1[i])[0] # # Index of the first node of the next element in elems.nodes - connectListNodes[i] = np.where(data[:,0] == N1[i])[0] # Index of the node in boundary.nodes - if eData[connectListElems[i],2] == upperGlobTE: - upperTE = 1 - i += 1 - # Sort the pressure side - connectListElems[i] = np.where(eData[:,2] == globStag)[0] - connectListNodes[i] = np.where(data[:,0] == upperGlobTE)[0] - N1[i] = eData[connectListElems[i],2] - while lowerTE == 0: - N1[i+1] = eData[connectListElems[i],1] # First node of the element - connectListElems[i+1] = np.where(eData[:,2] == N1[i+1])[0] # # Index of the second node of the next element in elems.nodes - connectListNodes[i+1] = np.where(data[:,0] == N1[i+1])[0] # Index of the node in boundary.nodes - if eData[connectListElems[i+1],1] == lowerGlobTE: - lowerTE = 1 - i += 1 - connectListNodes[i+1] = np.where(data[:,0] == lowerGlobTE)[0] - data[:,0] = data[connectListNodes,0] - data[:,1] = data[connectListNodes,1] - data[:,2] = data[connectListNodes,2] - data[:,3] = data[connectListNodes,3] - data[:,4] = data[connectListNodes,4] - data[:,5] = data[connectListNodes,5] - data[:,6] = data[connectListNodes,6] - data[:,7] = data[connectListNodes,7] - data[:,8] = data[connectListNodes,8] - data[:,9] = data[connectListNodes,9] - # Separated upper and lower part - data = np.delete(data,0,1) - uData = data[0:np.argmax(data[:,0])+1] - lData = data[np.argmax(data[:,0])+1:None] - lData = np.insert(lData, 0, uData[0,:], axis = 0) #double the stagnation point - return connectListNodes, connectListElems,[uData, lData] -} diff --git a/vii/src/wDartCoupler.h b/vii/src/wDartCoupler.h deleted file mode 100644 index 8910ecda39b957620d86509fe04c14d254ea6797..0000000000000000000000000000000000000000 --- a/vii/src/wDartCoupler.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef WDARTCOUPLER_H -#define WDARTCOUPLER_H - -#include "vii.h" -#include "../../dart/src/wNewton.h" -#include "../../dart/src/wBlowing.h" -#include "wViscSolver.h" - -namespace vii -{ - -class DART_API DartCoupler -{ - -private: - unsigned long maxCouplIter; - double tol; - - -public: - - Newton *invSolver; - ViscSolver *viscSolver; - std::vector<Blowing> *blw; - - - DartCoupler(); - ~DartCoupler(); - Run(); - ImposeBlowing(); - ImposeInviscidBC(); - -}; -} // namespace dart -#endif //WDARTCOUPLER_H diff --git a/vii/src/wInvBnd.cpp b/vii/src/wInvBnd.cpp index 8d8722792b13f37e4afb4a033f2e8da8d05a60af..7c28ab295d51809c854b98880090b35a98b14b38 100644 --- a/vii/src/wInvBnd.cpp +++ b/vii/src/wInvBnd.cpp @@ -11,13 +11,6 @@ /* --- Project includes -------------------------------------------------------------- */ #include "wInvBnd.h" -#include <iostream> -#include <vector> -#include <unordered_set> -#include <iomanip> -#include <fstream> -#include <iostream> -#include <iomanip> /* --- Namespaces -------------------------------------------------------------------- */ diff --git a/vii/src/wInvBnd.h b/vii/src/wInvBnd.h index b3f714cad2bc913f878b01546a2a04c430e26817..6cfb14fbd8601221703b688b20031ad7c254feee 100644 --- a/vii/src/wInvBnd.h +++ b/vii/src/wInvBnd.h @@ -2,7 +2,6 @@ #define WINVBND_H #include "vii.h" -#include "wBLRegion.h" #include <vector> #include <iostream> diff --git a/vii/src/wTimeSolver.cpp b/vii/src/wTimeSolver.cpp index dd420136a76b9353f2b23017068625233f1c60e5..be6e0e7570c1ace5c50c68e9364ae9cd5bf05296 100644 --- a/vii/src/wTimeSolver.cpp +++ b/vii/src/wTimeSolver.cpp @@ -1,11 +1,7 @@ #include "wTimeSolver.h" #include "wBLRegion.h" #include "wViscFluxes.h" -#include "wInvBnd.h" #include <Eigen/Dense> -#include <iostream> -#include <vector> -#include <cmath> using namespace Eigen; using namespace tbox; diff --git a/vii/src/wTimeSolver.h b/vii/src/wTimeSolver.h index af485d4cdb6686206da9a04252711821ba256569..e80e714dfcd3853aac9b0dee52db53448c2eb0c4 100644 --- a/vii/src/wTimeSolver.h +++ b/vii/src/wTimeSolver.h @@ -3,8 +3,6 @@ #include "vii.h" #include "wViscFluxes.h" -#include <vector> -#include <string> namespace vii { diff --git a/vii/src/wViscFluxes.cpp b/vii/src/wViscFluxes.cpp index 7fe7947fbfab3dd2f0b0ff734502c6c0b927dce6..1b667ba5dfa3a88f3c768a753c0001c078623bcb 100644 --- a/vii/src/wViscFluxes.cpp +++ b/vii/src/wViscFluxes.cpp @@ -2,12 +2,7 @@ #include "wViscFluxes.h" #include "wBLRegion.h" -#include "wInvBnd.h" -#include <iostream> #include <Eigen/Dense> -#include <cmath> -#include <algorithm> -#include <string> using namespace vii; using namespace Eigen; diff --git a/vii/src/wViscFluxes.h b/vii/src/wViscFluxes.h index a60bf35f34c0e2099b608e539694c2f4fd196a44..823a070e298f8c407d7d06b8af093a1424eb9988 100644 --- a/vii/src/wViscFluxes.h +++ b/vii/src/wViscFluxes.h @@ -4,8 +4,6 @@ #include "vii.h" #include "wBLRegion.h" #include <Eigen/Dense> -#include <vector> -#include <string> namespace vii { diff --git a/vii/src/wViscMesh.cpp b/vii/src/wViscMesh.cpp index 9cb054452bdf98b13c0f193d6493d7ab10d08d37..82f742274474f98069fbe55731186d0c5dcc8e64 100644 --- a/vii/src/wViscMesh.cpp +++ b/vii/src/wViscMesh.cpp @@ -11,8 +11,6 @@ /* --- Project includes -------------------------------------------------------------- */ #include "wViscMesh.h" -#include <iostream> -#include <vector> #include <cmath> /* --- Namespaces -------------------------------------------------------------------- */ diff --git a/vii/src/wViscMesh.h b/vii/src/wViscMesh.h index 0531097bc4bcbec7c300c2278860b0f9109134b7..5dbec9743957e00eca017f9c7905769780a3ae19 100644 --- a/vii/src/wViscMesh.h +++ b/vii/src/wViscMesh.h @@ -3,8 +3,6 @@ #include "vii.h" #include "wBLRegion.h" -#include <vector> -#include <iostream> namespace vii { diff --git a/vii/src/wViscSolver.cpp b/vii/src/wViscSolver.cpp index e4270fed1af41494016b3686cacc5a1632cf4e54..c7dcb053c7c74a6f7f95b158e1e62178cc0080e5 100644 --- a/vii/src/wViscSolver.cpp +++ b/vii/src/wViscSolver.cpp @@ -13,10 +13,7 @@ #include "wViscSolver.h" #include "wBLRegion.h" #include "wTimeSolver.h" -#include <iostream> #include <iomanip> -#include <vector> -#include <cmath> /* --- Namespaces -------------------------------------------------------------------- */ @@ -100,8 +97,8 @@ ViscSolver::~ViscSolver() */ int ViscSolver::Run(unsigned int const couplIter) { - bool lockTrans=false; - int pointExitCode = 0; + bool lockTrans=false; /* Flagging activation of transition routines */ + int pointExitCode = 0; /* Output of pseudo time integration (0: converged; -1: unsuccessful, failed; >0: unsuccessful nb iter) */ solverExitCode = 0; for (size_t iSec=0; iSec<Sections.size(); ++iSec) @@ -126,7 +123,7 @@ int ViscSolver::Run(unsigned int const couplIter) Sections[iSec][0]->xtr = 1.; /* Upper side initial xtr */ Sections[iSec][1]->xtr = 1.; /* Lower side initial xtr */ - Sections[iSec][2]->xtr = 0.; /* Wake initial xtr (full turbulent) */ + Sections[iSec][2]->xtr = 0.; /* Wake initial xtr (fully turbulent) */ Sections[iSec][0]->SetStagBC(Re); Sections[iSec][1]->SetStagBC(Re); @@ -137,7 +134,7 @@ int ViscSolver::Run(unsigned int const couplIter) if (verbose>0){std::cout << Sections[iSec][iRegion]->name << " ";} - /* Check if we need to enter safe mode */ + /* Check if safe mode is required */ if (couplIter == 0 || Sections[iSec][iRegion]->mesh->GetDiffnElm() != 0 || stagPtMvmt[iSec] == true || solverExitCode != 0) { @@ -165,6 +162,7 @@ int ViscSolver::Run(unsigned int const couplIter) Sections[iSec][iRegion]->invBnd->SetVtOld(ueOld); } + /* Keyword annoncing iteration safety level */ if (verbose>1){std::cout << "restart. ";} } @@ -174,6 +172,7 @@ int ViscSolver::Run(unsigned int const couplIter) tSolver->SetitFrozenJac(5); tSolver->SetinitSln(false); + /* Keyword annoncing iteration safety level */ if (verbose>1){std::cout << "update. ";} } @@ -276,7 +275,7 @@ int ViscSolver::Run(unsigned int const couplIter) } /** - * @brief Check whether instabilities are growing in the laminar boundary layer. + * @brief Check whether or not instabilities are growing in the laminar boundary layer. */ void ViscSolver::CheckWaves(size_t iPoint, BLRegion *bl) { @@ -302,14 +301,16 @@ void ViscSolver::AverageTransition(size_t iPoint, BLRegion *bl, int forced) unsigned int nVar = bl->GetnVar(); - // Save laminar solution. + /* Save laminar solution. */ + std::vector<double> lamSol(nVar, 0.0); for (size_t k = 0; k < lamSol.size(); ++k) { lamSol[k] = bl->U[iPoint * nVar + k]; } - // Set up turbulent portion boundary condition. + /* Set up turbulent portion boundary condition. */ + bl->transMarker = iPoint; /* Save transition marker */ /* Loop over remaining points in the region */ @@ -319,7 +320,6 @@ void ViscSolver::AverageTransition(size_t iPoint, BLRegion *bl, int forced) } /* Compute transition location */ - //std::cout << "Trans " << bl->mesh->Getx(iPoint) << std::endl; bl->xtr = (bl->GetnCrit() - bl->U[(iPoint - 1) * nVar + 2]) * ((bl->mesh->Getx(iPoint) - bl->mesh->Getx(iPoint - 1)) / (bl->U[iPoint * nVar + 2] - bl->U[(iPoint - 1) * nVar + 2])) + bl->mesh->Getx(iPoint - 1); /* Percentage of the subsection corresponding to a turbulent flow */ diff --git a/vii/tests/bli2.py b/vii/tests/bli2.py index c46a10a8e9a8fc058a3c827bd315b07aff9bf728..cf3b47694b2f44608f591eb48f8f30295baca732 100644 --- a/vii/tests/bli2.py +++ b/vii/tests/bli2.py @@ -57,7 +57,7 @@ def main(): # define flow variables Re = 1e7 - alpha = 5.*math.pi/180 + alpha = 2.*math.pi/180 M_inf = 0. CFL0 = 1