using Printf include("Grid.jl") include("Boundary.jl") include("Core/BTCS.jl") @enum APPROACH BTCS @enum SOLVER EIGEN_LU_SOLVER @enum CONSOLE_OUTPUT CONSOLE_OUTPUT_OFF CONSOLE_OUTPUT_ON CONSOLE_OUTPUT_VERBOSE @enum CSV_OUTPUT CSV_OUTPUT_OFF CSV_OUTPUT_ON CSV_OUTPUT_VERBOSE CSV_OUTPUT_XTREME # Create the Simulation class struct Simulation{T,approach,solver} grid::Grid{T} bc::Boundary{T} approach::APPROACH solver::SOLVER iterations::Int timestep::T consoleOutput::CONSOLE_OUTPUT csvOutput::CSV_OUTPUT function Simulation(grid::Grid{T}, bc::Boundary{T}, approach::APPROACH=BTCS, solver::SOLVER=EIGEN_LU_SOLVER, iterations::Int=1, timestep::T=0.1, consoleOutput::CONSOLE_OUTPUT=CONSOLE_OUTPUT_OFF, csvOutput::CSV_OUTPUT=CSV_OUTPUT_OFF) where {T} new{T,APPROACH,SOLVER}(grid, bc, approach, solver, iterations, timestep, consoleOutput, csvOutput) end end function createCSVfile(simulation::Simulation{T,approach,solver})::IOStream where {T,approach,solver} appendIdent = 0 approachString = (simulation.approach == BTCS) ? "BTCS" : "UNKNOWN" # Add other approaches as needed row = simulation.grid.rows col = simulation.grid.cols numIterations = simulation.iterations filename = string(approachString, "_", row, "_", col, "_", numIterations, ".csv") while isfile(filename) appendIdent += 1 filename = string(approachString, "_", row, "_", col, "_", numIterations, "-", appendIdent, ".csv") end # Write boundary conditions if required if simulation.csvOutput == CSV_OUTPUT_XTREME open(filename, "w") do file writeBoundarySideValues(file, simulation.bc, LEFT) writeBoundarySideValues(file, simulation.bc, RIGHT) if simulation.grid.dim == 2 writeBoundarySideValues(file, simulation.bc, TOP) writeBoundarySideValues(file, simulation.bc, BOTTOM) end write(file, "\n\n") end end file = open(filename, "a") return file end function writeBoundarySideValues(file, bc::Boundary{T}, side) where {T} values::Vector{BoundaryElement} = getBoundarySide(bc, side) formatted_values = join(map(getValue, values), " ") write(file, formatted_values, "\n") end function printConcentrationsCSV(simulation::Simulation{T,approach,solver}, file::IOStream) where {T,approach,solver} concentrations = simulation.grid.concentrations[] for row in eachrow(concentrations) formatted_row = [Printf.@sprintf("%.6g", x) for x in row] # Format each element like is done in the C++ version using Eigen3 println(file, join(formatted_row, " ")) end println(file) # Add extra newlines for separation println(file) end function printConcentrations(simulation::Simulation{T,approach,solver}) where {T,approach,solver} println(simulation.grid.concentrations[]) end function run(simulation::Simulation{T,approach,solver}) where {T,approach,solver} file = nothing try if simulation.csvOutput > CSV_OUTPUT_OFF file = createCSVfile(simulation) end function simulationStepCallback() if simulation.consoleOutput >= CONSOLE_OUTPUT_VERBOSE printConcentrations(simulation) end if simulation.csvOutput >= CSV_OUTPUT_VERBOSE printConcentrationsCSV(simulation, file) end end if simulation.approach == BTCS runBTCS(simulation.grid, simulation.bc, simulation.timestep, simulation.iterations, simulationStepCallback) else error("Undefined approach!") end if simulation.consoleOutput >= CONSOLE_OUTPUT_ON printConcentrations(simulation) end if simulation.csvOutput >= CSV_OUTPUT_ON printConcentrationsCSV(simulation, file) end finally if file !== nothing close(file) end end end function setTimestep(simulation::Simulation{T,approach,solver}, timestep::T) where {T,approach,solver} return Simulation(simulation.grid, simulation.bc, simulation.approach, simulation.solver, simulation.iterations, timestep, simulation.consoleOutput, simulation.csvOutput) end function setIterations(simulation::Simulation{T,approach,solver}, iterations::Int) where {T,approach,solver} return Simulation(simulation.grid, simulation.bc, simulation.approach, simulation.solver, iterations, simulation.timestep, simulation.consoleOutput, simulation.csvOutput) end function setOutputConsole(simulation::Simulation{T,approach,solver}, consoleOutput::CONSOLE_OUTPUT) where {T,approach,solver} return Simulation(simulation.grid, simulation.bc, simulation.approach, simulation.solver, simulation.iterations, simulation.timestep, consoleOutput, simulation.csvOutput) end function setOutputCSV(simulation::Simulation{T,approach,solver}, csvOutput::CSV_OUTPUT) where {T,approach,solver} return Simulation(simulation.grid, simulation.bc, simulation.approach, simulation.solver, simulation.iterations, simulation.timestep, simulation.consoleOutput, csvOutput) end