#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 #include // timing #include #include #include #include #include "precice/precice.hpp" #include //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 steps = 100; // 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 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 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 wetNodes = mesh_c.TopNodes(); int numberOfVertices = wetNodes.size(); cout << numberOfVertices << " TOP NODES " << endl; // Determine coordinates of "wet" vertices std::vector allCoords = mesh_c.GetCoords(); std::vector 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 vertexIDs(numberOfVertices); participantSolid.setMeshVertices(meshName, coords, vertexIDs); // ----- initialize read- and write-data std::vector temperature(numberOfVertices * meshDim); // read-data std::vector heatFlux(numberOfVertices * meshDim); // 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; //while (average_coffee_temperature > goal_temp) while (percentage_temp_reached > goal_perc) { preciceDt = participantSolid.getMaxTimeStepSize(); solverDt = 1.0; dt = min(preciceDt, solverDt); // ----- read temperature computed by openFOAM simulation ----- participantSolid.readData("Solid-Mesh", "Temperature", vertexIDs, dt, temperature); { // TODO: SET THE MESH TO THE INCOMING TEMPERATURE // "initNewTemp(temperature)" } // ----- solve time step ----- vector G(Mdt.Nrows(), 0.0); Mdt.Mult(G, uv); // G = M/dt * u_{n} vector 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; time_count += dt; // ----- write the heat-flux, so openFOAM can read it { // TODO: COMPUTE THE HEAT-FLUX FROM THE NEW uv TEMPERATURE SOLUTION // "computeHeatFlux(heatFlux)" } participantSolid.writeData("Solid-Mesh", "Heat-Flux", vertexIDs, heatFlux); // ----- advance preCICE ----- participantSolid.advance(dt); time_count += dt; } auto t4 = system_clock::now(); // stop timer auto duration = duration_cast(t4 - t3); // duration in microseconds double t_diff = static_cast(duration.count()) / 1e6; // overall duration in seconds cout << "\n\nJacobiSolve: timing in sec. : " << t_diff << endl; // ----- free data, close communication ----- participantSolid.finalize(); return 0; }