Exported from Notepad++
1 # Mostapha Abdelaziz
2 # ODE
3 #
4
5 # function that prints the first menu and validates input
6 menuOne <- function(){
7 # set variable for loop
8 menuOption <- "-1"
9
10 # print menu
11 writeLines("\nChoose the method for solving the ODE of
12 𝜃(𝑡) = 0.1 cos4𝑡 + 0.2sin4𝑡 + 2.9𝑒 ^(−2𝑡)
13 \n1. Euler's Method
14 \n2. Runge-Kutta 4th Order Method
15 \n3. Quit\n")
16 # take input
17 menuOption <- readline(prompt = "Please enter your choice: ")
18 # if it is not 1 or 2 ask again
19 while (menuOption != "1" && menuOption != "2" && menuOption != "3"){
20 writeLines("You must enter \"1\", \"2\" or \"3\", try again.")
21 menuOption <- readline(prompt = "Please enter your choice: ")
22 }
23
24 # return validated input
25 return(menuOption)
26 }
27
28 # function that prints the second menu and validates input
29 menuTwo <- function(){
30 # set variable for loop
31 menuOption <- "3"
32
33 # print menu
34 writeLines("\nChoose step size \"h\" (0.8, 0.2, 0.05)")
35 # take input
36 menuOption <- readline(prompt = "Please enter your choice: ")
37 # if it is not 1 or 2 ask again
38 while (menuOption != "0.8" && menuOption != "0.2"
39 && menuOption != "0.05" && menuOption != ".8"
40 && menuOption != ".2" && menuOption != ".05"){
41 writeLines("You must enter \"0.8\" or \"0.2\" or \"0.05\", try again.")
42 menuOption <- readline(prompt = "Please enter your choice: ")
43 }
44
45 # return validated input
46 return(menuOption)
47 }
48
49 # function for solving ODE using euler method
50 euler <- function(xVec, ynot, stepSize){
51 # create a vector for y values
52 yVec <- vector(mode = "numeric", length = length(xVec))
53 # define ynot as provided value
54 yVec[1] <- ynot
55
56 # loop through to calculate each y value
57 for(i in 1:length(xVec)){
58 # f(x,y) = cos4x - 2y y(i+1) = yi + f(x,y)h
59 yVec[i+1] <- yVec[i] + ( (cos(4*xVec[i]) - 2*yVec[i]) * stepSize )
60 }
61
62 # return our y values
63 return(yVec)
64 }
65
66 # function for solving ODE using runge-kutta 4th order
67 rungekutta <- function(xVec, ynot, stepSize){
68 # create a vector for y values
69 yVec <- vector(mode = "numeric", length = length(xVec))
70 # define ynot as provided value
71 yVec[1] <- ynot
72
73 # loop through to calculate each y value
74 for(i in 1:length(xVec)){
75 # f(x,y) = cos4x - 2y y(i+1) = yi + f(x,y)h
76 # calculate k1,k2,k3,k4
77 k1 <- (cos(4*xVec[i]) - 2*yVec[i])
78 k2 <- (cos(4*(xVec[i] + 0.5*stepSize)) - 2*(yVec[i] + 0.5*k1*stepSize))
79 k3 <- (cos(4*(xVec[i] + 0.5*stepSize)) - 2*(yVec[i] + 0.5*k2*stepSize))
80 k4 <- (cos(4*(xVec[i] + stepSize)) - 2*(yVec[i] + k3*stepSize))
81
82 # caclulate yi
83 yVec[i+1] <- yVec[i] + ( ((1/6)*(k1 + 2*k2 + 2*k3 + k4)) * stepSize )
84 }
85
86 # return our y values
87 return(yVec)
88 }
89
90 # function for calculating the solution
91 solution <- function(xVec, stepSize){
92 # create a vector for y values
93 yVec <- vector(mode = "numeric", length = length(xVec))
94
95 # loop through to calculate each y value
96 for(i in 1:length(xVec)){
97 # f(x) = 0.1cos4x + 0.2sin4x + 2.9e^(-2x)
98 yVec[i] <- 0.1*cos(4*xVec[i]) + 0.2*sin(4*xVec[i]) + 2.9*exp(-2*xVec[i])
99 }
100
101 # return our y values
102 return(yVec)
103 }
104
105 # function for calculating relative error
106 errors <- function(yEstimate, yExact){
107 yVec <- vector(mode = "numeric", length = length(yExact))
108 # loop to calculate error
109 for(i in 1:length(yExact)){
110 absError <- abs(yEstimate[i] - yExact[i])
111 yVec[i] <- abs(absError / yExact[i]) * 100
112 }
113
114 # return vector
115 return(yVec)
116 }
117
118 calculate <- function(menuOption){
119 start <- 0
120 end <- 2
121 ynot <- 3
122
123 # print the second menu
124 stepSize <- as.numeric(menuTwo())
125 # create x vector
126 xVec <- seq(from = start, to = end, by = stepSize)
127
128 # if they chose eulers or runge-kutta call the relevant function
129 if (menuOption == "1"){
130 title <- "Euler's Method Estimated Temperature vs Exact"
131 yEstimate <- euler(xVec, ynot, stepSize)
132 } else {
133 title <- "Runge Kutta's Method Estimated Temperature vs Exact"
134 yEstimate <- rungekutta(xVec, ynot, stepSize)
135 }
136
137 # calculate the exact values
138 yExact <- solution(xVec, stepSize)
139
140 # caclulate the percent error
141 errors <- errors(yEstimate, yExact)
142
143 # print table
144 writeLines("")
145 table <- matrix(c(xVec[2:length(xVec)], yExact[2:length(yExact)],
146 yEstimate[2:length(yExact)], errors[2:length(yExact)]), ncol = 4)
147 colnames(table) <- c("Time(seconds)", " Exact Temp (C)", " Estimated Temp (C)", " Percentage Error (%)")
148 prmatrix(table, rowlab=rep("",length(yExact)))
149
150 # plot a graph of the exact temperature vs the estimated temperature
151 matplot(table[,1], table[,2:3], type=c("l","p"), lty=1, pch=1 , col=c(1,2),
152 main=title, sub = "Exact Values as a black line, Estimated Values as red points",
153 xlab="Time (Seconds)", ylab="Temperature (C)")
154 }
155
156 # main function to loop through menus
157 main <- function(){
158 menuOption <- "-1"
159
160 # loop through menu indefinitely
161 while(menuOption != 3){
162 # print first menu
163 menuOption <- menuOne()
164 # continue unless user quits
165 if (menuOption != "3"){
166 calculate(menuOption)
167 } else {
168 writeLines("Quitting...")
169 }
170
171 } # end of loop
172 }
173
174 # call function to run program
175 main()
176
177