36 IcoFoamInterface(
int rank,
int plotEveryTimestep,
double channelheight, std::string dict, std::string folder,
39 mesh(Foam::IOobject(Foam::fvMesh::defaultRegion, runTime.timeName(), runTime, Foam::IOobject::MUST_READ)),
40 transportProperties(Foam::IOobject(
"transportProperties", runTime.constant(), mesh, Foam::IOobject::MUST_READ_IF_MODIFIED, Foam::IOobject::NO_WRITE)),
41 nu(
"nu", Foam::dimViscosity, transportProperties),
42 p(Foam::IOobject(
"p", runTime.timeName(), mesh, Foam::IOobject::MUST_READ, Foam::IOobject::AUTO_WRITE), mesh),
43 U(Foam::IOobject(
"U", runTime.timeName(), mesh, Foam::IOobject::MUST_READ, Foam::IOobject::AUTO_WRITE), mesh),
44 phi(Foam::IOobject(
"phi", runTime.timeName(), mesh, Foam::IOobject::READ_IF_PRESENT, Foam::IOobject::AUTO_WRITE), Foam::fvc::flux(U)), piso(mesh),
45 _boundariesWithMD(boundariesWithMD), _dx(std::cbrt(Foam::max(mesh.cellVolumes()))), _channelheight(channelheight), _rank(rank),
46 _plotEveryTimestep(plotEveryTimestep), _uWall(uWall) {
50 Foam::setRefCell(p, mesh.solutionDict().subDict(
"PISO"), pRefCell, pRefValue);
51 mesh.setFluxRequired(p.name());
54 virtual ~IcoFoamInterface() {
58 if (_boundaryIndicesInner) {
59 delete[] _boundaryIndicesInner;
60 _boundaryIndicesInner = NULL;
62 if (_boundaryIndices) {
63 delete[] _boundaryIndices;
64 _boundaryIndices = NULL;
74 size_t number = floor(dt / runTime.deltaTValue() + 0.5);
75 for (
size_t i = 0; i < number; i++) {
78 Info <<
"Time = " << runTime.timeName() << nl << endl;
81 fvVectorMatrix UEqn(fvm::ddt(U) + fvm::div(phi, U) - fvm::laplacian(nu, U));
82 if (piso.momentumPredictor()) {
83 solve(UEqn == -fvc::grad(p));
86 while (piso.correct()) {
87 volScalarField rAU(1.0 / UEqn.A());
88 volVectorField HbyA(constrainHbyA(rAU * UEqn.H(), U, p));
89 surfaceScalarField phiHbyA(
"phiHbyA", fvc::flux(HbyA) + fvc::interpolate(rAU) * fvc::ddtCorr(U, phi));
90 adjustPhi(phiHbyA, U, p);
93 constrainPressure(p, U, phiHbyA, rAU);
96 while (piso.correctNonOrthogonal()) {
98 fvScalarMatrix pEqn(fvm::laplacian(rAU, p) == fvc::div(phiHbyA));
99 pEqn.setReference(pRefCell, pRefValue);
101 if (piso.finalNonOrthogonalIter()) {
102 phi = phiHbyA - pEqn.flux();
105 U = HbyA - rAU * fvc::grad(p);
106 U.correctBoundaryConditions();
117 const Foam::vector foamPosition(pos[0], pos[1], pos[2]);
118 const int foamIndice = U.mesh().findCell(foamPosition);
119 if (foamIndice > 0) {
127 void setWallVelocity(tarch::la::Vector<3, double> wallVelocity)
override {
128 const size_t pointsInBoundary = U.boundaryFieldRef()[0].size();
129 for (
size_t i = 0; i < pointsInBoundary; i++) {
130 U.boundaryFieldRef()[0][i].x() = wallVelocity[0];
131 U.boundaryFieldRef()[0][i].y() = wallVelocity[1];
132 U.boundaryFieldRef()[0][i].z() = wallVelocity[2];
137 void setMDBoundaryValues(coupling::datastructures::FlexibleCellContainer<3>& md2macroBuffer) {
141 size_t pointsWritten = 0;
143 coupling::datastructures::CouplingCell<3>* cell;
144 for (
auto pair : md2macroBuffer) {
145 std::tie(cell, idx) = pair;
146 if(_boundaryPointMap.count(idx) > 0){
147 for(
auto[it, rangeEnd] = _boundaryPointMap.equal_range(idx); it != rangeEnd; ++it){
148 unsigned int boundarypoint = it->second;
149 tarch::la::Vector<3, double> localOuterVel = getVelocity(_boundaryPointsOuter.at(boundarypoint));
151 _boundaryIndices[boundarypoint]->x() = (localOuterVel[0] + localInnerVel[0]) * 0.5;
152 _boundaryIndices[boundarypoint]->y() = (localOuterVel[1] + localInnerVel[1]) * 0.5;
153 _boundaryIndices[boundarypoint]->z() = (localOuterVel[2] + localInnerVel[2]) * 0.5;
158 if(pointsWritten != _numberBoundaryPoints)
159 throw std::runtime_error(std::string(
"IcoFoamInterface::setMDBoundaryValues(): boundary point mapping error!"));
164 void setupMDBoundary() {
168 size_t innerMDBoundaryIndex = 0;
169 while (_boundariesWithMD[innerMDBoundaryIndex] == 0) {
170 innerMDBoundaryIndex++;
172 _numberBoundaryPoints = 6 * U.boundaryFieldRef()[innerMDBoundaryIndex].size();
173 _boundaryPointsOuter.resize(_numberBoundaryPoints);
174 _boundaryIndicesInner =
new I00[_numberBoundaryPoints];
175 _boundaryIndices =
new Foam::vector*[_numberBoundaryPoints];
177 const unsigned int dim = 3;
178 for (
size_t boundary = 0; boundary < 12; boundary++) {
179 if (_boundariesWithMD[boundary] == 1) {
180 size_t MDPointsPerBoundary = _numberBoundaryPoints / 6;
181 for (
size_t j = 0; j < MDPointsPerBoundary; j++) {
182 _boundaryIndices[counter] = &(U.boundaryFieldRef()[boundary][j]);
183 _boundaryPointsOuter[counter] = getOuterPointFromBoundary(boundary, j);
184 _boundaryIndicesInner[counter] = IDXS.getCellIndex(getInnerPointFromBoundary(boundary, j));
189 if(counter != _numberBoundaryPoints)
190 throw std::runtime_error(std::string(
"IcoFoamInterface::setupMDBoundary(): boundary point mapping error!"));
191 for (
size_t i = 0; i < _numberBoundaryPoints; i++)
192 _boundaryPointMap.insert({_boundaryIndicesInner[i], i});
197 const tarch::la::Vector<3, double> getOuterPointFromBoundary(
const int layer,
const int index) {
198 const Foam::vectorField FoamCoord(U.boundaryFieldRef()[layer].patch().Cf()[index] - (U.boundaryFieldRef()[layer].patch().nf() * _dx * 0.5));
199 const tarch::la::Vector<3, double> FoamCoordVector(FoamCoord[0][0], FoamCoord[0][1], FoamCoord[0][2]);
200 return FoamCoordVector;
204 const tarch::la::Vector<3, double> getInnerPointFromBoundary(
const int layer,
const int index) {
205 const Foam::vectorField FoamCoord(U.boundaryFieldRef()[layer].patch().Cf()[index] + (U.boundaryFieldRef()[layer].patch().nf() * _dx * 0.5));
206 const tarch::la::Vector<3, double> FoamCoordVector(FoamCoord[0][0], FoamCoord[0][1], FoamCoord[0][2]);
207 return FoamCoordVector;
211 const tarch::la::Vector<3, double> getSecondOuterPointFromBoundary(
const int layer,
const int index) {
212 const Foam::vectorField FoamCoord(U.boundaryFieldRef()[layer].patch().Cf()[index] + (U.boundaryFieldRef()[layer].patch().nf() * _dx * 1.5));
213 const tarch::la::Vector<3, double> FoamCoordVector(FoamCoord[0][0], FoamCoord[0][1], FoamCoord[0][2]);
214 return FoamCoordVector;
218 const double getAnalyticalCouetteU(
const double& pos)
const {
219 const double pi = 3.141592653589793238;
220 double u_analytical = 0.0;
221 for (
int k = 1; k < 30; k++) {
222 u_analytical += 1.0 / k * std::sin(k * pi * pos / _channelheight) *
223 std::exp(-k * k * pi * pi / (_channelheight * _channelheight) * nu.value() * runTime.timeOutputValue());
225 return _uWall[0] * (1.0 - pos / _channelheight - 2.0 / pi * u_analytical);
230 if (_plotEveryTimestep < 1 || _timestepCounter % _plotEveryTimestep > 0)
232 std::stringstream ss;
233 ss <<
"velocity_" << _timestepCounter <<
".txt";
234 std::ofstream file(ss.str().c_str());
235 if (!file.is_open()) {
236 std::cout <<
"ERROR NumericalSolver::plottxt(): Could not open file " << ss.str() <<
"!" << std::endl;
239 std::stringstream velocity;
242 double y = _channelheight / 2;
243 double x = _channelheight / 2;
244 for (
double z = _dx / 2; z < _channelheight; z = z + _dx) {
245 const int foamIndice = U.mesh().findCell(Foam::vector(x, y, z));
247 if (foamIndice > 0) {
248 velocity << U[foamIndice][0] <<
", " << U[foamIndice][1] <<
", " << U[foamIndice][2] << std::endl;
251 file << velocity.str() << std::endl;
258 if (_plotEveryTimestep < 1) {
261 if (_timestepCounter % _plotEveryTimestep != 0) {
265 std::stringstream ss;
266 ss <<
"Continuum_Velocity_IcoFoam_" << _rank <<
"_" << _timestepCounter <<
".vtk";
267 std::ofstream file(ss.str().c_str());
268 if (!file.is_open()) {
269 std::cout <<
"ERROR NumericalSolver::plot(): Could not open file " << ss.str() <<
"!" << std::endl;
272 std::stringstream velocity;
274 file <<
"# vtk DataFile Version 2.0" << std::endl;
275 file <<
"MaMiCo FoamSolver" << std::endl;
276 file <<
"ASCII" << std::endl << std::endl;
277 file <<
"DATASET UNSTRUCTURED_GRID" << std::endl;
282 file <<
"POINTS " << U.mesh().nCells() <<
" float" << std::endl;
284 velocity << std::setprecision(12);
285 velocity <<
"POINT_DATA " << U.mesh().nCells() << std::endl;
286 velocity <<
"VECTORS velocity float" << std::endl;
290 for (
int i = 0; i < size; i++) {
292 file << U.mesh().C()[i][0] <<
" " << U.mesh().C()[i][1] <<
" " << U.mesh().C()[i][2] << std::endl;
293 velocity << U[i][0] <<
" " << U[i][1] <<
" " << U[i][2] << std::endl;
297 file << velocity.str() << std::endl;
303 bool skipRank()
const {
return !(_rank == 0); }
308 Foam::IOdictionary transportProperties;
309 Foam::dimensionedScalar nu;
310 Foam::volScalarField p;
311 Foam::volVectorField U;
312 Foam::surfaceScalarField phi;
313 Foam::pisoControl piso;
319 double _channelheight;
320 std::multimap<I00, unsigned int> _boundaryPointMap;
321 std::vector<tarch::la::Vector<3, double>> _boundaryPointsOuter;
322 I00* _boundaryIndicesInner{
nullptr};
323 Foam::vector** _boundaryIndices{
nullptr};
325 int _plotEveryTimestep;
326 int _timestepCounter{0};
328 Foam::label pRefCell{0};
329 Foam::scalar pRefValue{0.0};
330 size_t _numberBoundaryPoints{0};
331 tarch::la::Vector<3, double> _uWall;