228 lines
No EOL
7.7 KiB
C++
228 lines
No EOL
7.7 KiB
C++
// #include "../mgrid_2/geom.h"
|
|
// #include "../mgrid_2/getmatrix.h"
|
|
// #include "../mgrid_2/jacsolve.h"
|
|
// #include "../mgrid_2/userset.h"
|
|
// #include "../mgrid_2/vdop.h"
|
|
#include "geom.h"
|
|
#include "getmatrix.h"
|
|
#include "jacsolve.h"
|
|
#include "userset.h"
|
|
#include "vdop.h"
|
|
|
|
#include <cassert>
|
|
#include <chrono> // timing
|
|
#include <cmath>
|
|
#include <fstream>
|
|
#include <iostream>
|
|
#include <omp.h>
|
|
|
|
#include "precice/precice.hpp"
|
|
#include <sstream>
|
|
//using namespace precice;
|
|
|
|
using namespace std;
|
|
using namespace std::chrono; // timing
|
|
|
|
|
|
int main(int argc, char **argv )
|
|
{
|
|
// generating the mesh
|
|
Mesh const mesh_c("../generate_mesh/coffee_cup.txt", "../generate_mesh/coffee_cup_sd.txt");
|
|
bool ba = mesh_c.checkObtuseAngles();
|
|
if (ba) cout << "mesh corrected" << endl;
|
|
//mesh_c.DebugEdgeBased();
|
|
|
|
//gMesh_Hierarchy ggm(mesh_c, nrefine);
|
|
//const Mesh &mesh = ggm.finest();
|
|
//mesh.Debug();
|
|
//mesh_c.DebugEdgeBased();
|
|
|
|
// ##########################################
|
|
// Parameteres
|
|
// ##########################################
|
|
|
|
double dt = 1.0; // time step
|
|
int max_it = 300; // number of time iterations
|
|
double u_out = 18.0;
|
|
|
|
// ##########################################
|
|
// Assembling
|
|
// ##########################################
|
|
|
|
// Initializing FEM matrix !pattern! (only zero entries now)
|
|
FEM_Matrix SK(mesh_c); // CRS matrix
|
|
//SK.writeBinary("sparseMatrix.bin");
|
|
//SK.Debug();
|
|
|
|
vector<double> fv(SK.Nrows(), 0.0);
|
|
SK.CalculateRHS(fv, [](double x, double y) {return 0;}); // rhs (f=0)
|
|
|
|
SK.CalculateLaplace_mult(fv); // stiffness matrix (+K)
|
|
SK.AddMass_mult(fv, 1.0/dt); // add mass matrix (+M/dt)
|
|
SK.ApplyRobinBC_mult(fv, u_out); // apply Robin-bnd (+C = +F)
|
|
// SK = M/dt + K + C = F
|
|
|
|
// SK.Debug();
|
|
// SK.CheckRowSum();
|
|
// SK.CheckMatrix();
|
|
|
|
FEM_Matrix Mdt(mesh_c);
|
|
Mdt.AddMass_mult(fv, 1.0/dt); // mass matrix (Mdt = M/dt)
|
|
|
|
// Mdt.Debug();
|
|
// Mdt.CheckRowSum();
|
|
// Mdt.CheckMatrix();
|
|
|
|
// ##########################################
|
|
// Timestepping (M/dt + K + C) * u_{n+1} = F + M/dt * u_{n}
|
|
// ##########################################
|
|
|
|
|
|
// ################################## SIMULATION (iii) ##################################
|
|
// read vector from simulation (i)
|
|
vector<double> uv(SK.Nrows(), 0.0);
|
|
|
|
ifstream input_file("uv_1.txt");
|
|
for (size_t i = 0; i < uv.size(); ++i)
|
|
{
|
|
input_file >> uv[i];
|
|
}
|
|
|
|
double u0_coffee = 85.0;
|
|
mesh_c.Init_Solution_mult(uv, 1, [u0_coffee](double x, double y) -> double { return u0_coffee; }); // fluid
|
|
|
|
mesh_c.Visualize(uv);
|
|
|
|
auto t3 = system_clock::now(); // start timer
|
|
double average_coffee_temperature = u0_coffee;
|
|
double goal_temp = 50.0;
|
|
double goal_perc = 60.0;
|
|
double percentage_temp_reached = mesh_c.CheckTemp_mult(uv, 1, goal_temp);
|
|
|
|
// ------------------------ initialize preCICE ------------------------
|
|
int commRank = 0;
|
|
int commSize = 1;
|
|
std::string configFileName("../precice-config.xml");
|
|
std::string solverName("Solid");
|
|
std::string meshName("Solid-Mesh");
|
|
|
|
std::cout << "Running Solid-solver with preCICE config file \"" << configFileName << "\" and participant name \"" << solverName << "\".\n";
|
|
|
|
precice::Participant participantSolid(solverName, configFileName, commRank, commSize);
|
|
|
|
int meshDim = participantSolid.getMeshDimensions(meshName); // gets mesh dimensions (=2) from config file
|
|
|
|
// Determine number of "wet" vertices
|
|
vector<int> wetNodes = mesh_c.TopNodes();
|
|
int numberOfVertices = wetNodes.size();
|
|
|
|
cout << numberOfVertices << " TOP NODES " << endl;
|
|
|
|
// Determine coordinates of "wet" vertices
|
|
std::vector<double> allCoords = mesh_c.GetCoords();
|
|
std::vector<double> coords(numberOfVertices*meshDim);
|
|
for (size_t i = 0; i < numberOfVertices; ++i)
|
|
{
|
|
int currentNode = wetNodes[i];
|
|
double x = allCoords[2*wetNodes[i]]; // x-coord of node
|
|
double y = allCoords[2*wetNodes[i] + 1]; // y-coord of node
|
|
|
|
// cout << "x: " << x << " y: " << y << endl;
|
|
|
|
coords[2*i] = x;
|
|
coords[2*i + 1] = y;
|
|
|
|
}
|
|
|
|
std::vector<int> vertexIDs(numberOfVertices);
|
|
|
|
participantSolid.setMeshVertices(meshName, coords, vertexIDs);
|
|
|
|
// ----- initialize read- and write-data
|
|
//std::vector<double> temperature(numberOfVertices * meshDim); // read-data
|
|
//std::vector<double> heatFlux(numberOfVertices * meshDim); // write-data
|
|
std::vector<double> temperature(numberOfVertices); // read-data
|
|
std::vector<double> heatFlux(numberOfVertices); // write-data
|
|
|
|
|
|
double solverDt = 1.0; // solver time step size
|
|
double preciceDt = 1.0; // maximum precice time step size
|
|
dt = 1.0; // actual time step size
|
|
|
|
participantSolid.initialize();
|
|
|
|
|
|
// ------------------------ timestepping ------------------------
|
|
goal_temp = 50.0;
|
|
goal_perc = 60.0;
|
|
|
|
double time_count = 0;
|
|
int step = 0;
|
|
while (average_coffee_temperature > goal_temp && step < max_it)
|
|
//while (percentage_temp_reached > goal_perc)
|
|
for(int i = 0; i < 100; ++i)
|
|
{
|
|
preciceDt = participantSolid.getMaxTimeStepSize();
|
|
solverDt = 1.0;
|
|
dt = min(preciceDt, solverDt);
|
|
|
|
// ----- read temperature computed by openFOAM simulation -----
|
|
participantSolid.readData("Solid-Mesh", "Temperature", vertexIDs, dt, temperature);
|
|
for (int i = 0; i < numberOfVertices; ++i)
|
|
{
|
|
int nodeIndex = wetNodes[i];
|
|
uv[nodeIndex] = temperature[i] - 273.15;
|
|
}
|
|
//mesh_c.Visualize(uv);
|
|
|
|
|
|
// ----- solve time step -----
|
|
vector<double> G(Mdt.Nrows(), 0.0);
|
|
Mdt.Mult(G, uv); // G = M/dt * u_{n}
|
|
|
|
|
|
|
|
vector<double> H = fv;
|
|
for (size_t i = 0; i < Mdt.Nrows(); ++i)
|
|
{
|
|
H[i] += G[i]; // H = F + G
|
|
}
|
|
|
|
JacobiSolve(SK, H, uv); // solve: (M/dt + K + C) * u_{n+1} = F + M/dt * u_{n}
|
|
// ----- SK ----- ------ H -------
|
|
|
|
average_coffee_temperature = mesh_c.AverageVectorFunction_perSubdomain(uv, 1);
|
|
percentage_temp_reached = mesh_c.CheckTemp_mult(uv, 1, goal_temp);
|
|
cout << "Average coffee temperature: " << average_coffee_temperature << " after " << time_count << " seconds. " << endl;
|
|
cout << "% of elements above temperature " << goal_temp << "ºC: " << percentage_temp_reached << endl;
|
|
|
|
// ----- compute and write the heat-flux, so openFOAM can read it
|
|
for (int i = 0; i < numberOfVertices; ++i)
|
|
{
|
|
int nodeIndex = wetNodes[i];
|
|
heatFlux[i] = 30.0*(uv[nodeIndex] - 31.0); // alpha is assumed for air material at the top
|
|
}
|
|
participantSolid.writeData("Solid-Mesh", "Heat-Flux", vertexIDs, heatFlux);
|
|
|
|
|
|
// ----- advance preCICE -----
|
|
participantSolid.advance(dt);
|
|
|
|
|
|
time_count += dt;
|
|
++step;
|
|
}
|
|
auto t4 = system_clock::now(); // stop timer
|
|
auto duration = duration_cast<microseconds>(t4 - t3); // duration in microseconds
|
|
double t_diff = static_cast<double>(duration.count()) / 1e6; // overall duration in seconds
|
|
cout << "\n\nJacobiSolve: timing in sec. : " << t_diff << endl;
|
|
|
|
|
|
// ----- free data, close communication -----
|
|
participantSolid.finalize();
|
|
|
|
|
|
mesh_c.Visualize(uv);
|
|
|
|
return 0;
|
|
} |