def Plot_Single(self, NumPts=10): """ plots CFEM solution to BVP (red) with analytic MMS solution (blue) """ plt.figure(1) # xplot = linspace(self.bounds[0], self.bounds[1], 100) # plt.plot(xplot, self.u(xplot), linewidth = 2, color = 'blue') for el in range(0, self.nels): xL = self.xnod[self.nod[el, 0]] xR = self.xnod[self.nod[el, self.order[el]-1]] dx = (xR - xL)/2.0 xpp = linspace(xL, xR, NumPts) xww = (xpp-xL)/dx - 1.0 ypp = zeros(NumPts) for j in range(0, NumPts): psi, dpsi = shape(xww[j], self.order[el]) uhval = 0.0 for k in range(0, self.order[el]): mynum = self.nod[el, k] uhval += self.soln[mynum]*psi[k] ypp[j] = uhval plt.plot(xpp,ypp, ".-",linewidth=1, color = 'red') plt.xlabel('Space') plt.grid(True) plt.show()
def LocalError(self, x): """ computes the local error at some given point, x """ # get element number based on position, x el = 0 a = self.hel while a < self.bounds[1]: if x < a: break else: el += 1 a += self.hel if el > self.nels-1: print("\n\n in get_CellNum\n") print(" el for mat map in x is greater than the problem domain, this is a problem\n\n") sys.exit() # get left and right node position of element, el xL = self.xnod[self.nod[el, 0]] xR = self.xnod[self.nod[el, self.order[el]-1]] dx = (xR - xL)/2.0 # evaluation reference function at x in real element uval = self.u(x) # map x to reference element xww = (x-xL)/dx - 1.0 psi, dpsi = shape(xww, self.order[el]) uhval = 0.0 for k in range(0, self.order[el]): mynum = self.nod[el, k] uhval += self.soln[mynum]*psi[k] # get error at middle of given cell # print(" -> Computing Local Error at x={0:.4e}".format(x)) # print(" uval, uhval = {0:.4e}, {1:.4e}".format(uval, uhval)) self.loc_err = abs(uval - uhval)
def LinfError(self): """ computes the L_infty error from an MMS type BVP problem """ nw, xw, w = QP(self.maxord) self.linf_ErrVal = 0.0 self.linf_Loc = None ## set mesh parameters to spatial grid for el in range(0, self.nels): # for each element in all elements xL = self.xnod[self.nod[el, 0]] xR = self.xnod[self.nod[el, self.order[el]-1]] dx = (xR - xL)/2.0 for l in range(0, nw): x = xL + (1.0 + xw[l])*dx psi, dpsi = shape(xw[l], self.order[el]) uval = self.u(x) uhval = 0.0 for k in range(0, self.order[el]): mynum = self.nod[el, k] uhval += self.soln[mynum]*psi[k] if abs(uval-uhval) > self.linf_ErrVal: self.linf_ErrVal = abs(uval-uhval) self.linf_Loc = x if self.linf_Loc == None: print("Max error not found! That doesn't make sense...") sys.exit()
def L2Error(self): """ computes the L2 error from an MMS type BVP problem """ nw, xw, w = QP(self.maxord) self.l2Err = 0.0 self.h1Err = 0.0 for el in range(0, self.nels): xL = self.xnod[self.nod[el, 0]] xR = self.xnod[self.nod[el, self.order[el]-1]] dx = (xR - xL)/2.0 for l in range(0, nw): x = xL + (1.0 + xw[l])*dx psi, dpsi = shape(xw[l], self.order[el]) uval = self.u(x) duval = self.up(x) uhval = 0.0 duhval = 0.0 for k in range(0, self.order[el]): mynum = self.nod[el, k] uhval += self.soln[mynum]*psi[k] duhval += self.soln[mynum]*dpsi[k]/dx # complete integration over element self.l2Err += (uval-uhval)**2 *w[l]*dx self.h1Err += (duval-duhval)**2 *w[l]*dx self.l2Err = sqrt(self.l2Err) self.h1Err = sqrt(self.l2Err + self.h1Err)
def Plot(self, NumPts=10, string="CFEM"): """ plots CFEM solution to BVP (red) with analytic MMS solution (blue) """ plt.figure(1) # xplot = linspace(self.bounds[0], self.bounds[1], 100) # plt.plot(xplot, self.u(xplot), linewidth = 2, color = 'blue') for el in range(0, self.nels): xL = self.xnod[self.nod[el, 0]] xR = self.xnod[self.nod[el, self.order[el]-1]] dx = (xR - xL)/2.0 xpp = linspace(xL, xR, NumPts) xww = (xpp-xL)/dx - 1.0 ypp = zeros(NumPts) for j in range(0, NumPts): psi, dpsi = shape(xww[j], self.order[el]) uhval = 0.0 for k in range(0, self.order[el]): mynum = self.nod[el, k] uhval += self.soln[mynum]*psi[k] ypp[j] = uhval # if string == "DFEM": # plt.plot(xpp,ypp, ".-",linewidth=1, color = 'blue') # else: # plt.plot(xpp,ypp, ".-",linewidth=1, color = 'red') if self.nels == 16: plt.plot(xpp, ypp, ".-", linewidth=1, color='red') elif self.nels == 32: plt.plot(xpp,ypp, ".-",linewidth=1, color = 'blue') elif self.nels == 64: plt.plot(xpp,ypp, ".-",linewidth=1, color = 'green') # plt.title("Exact solution (blue) and BVP {0} solution (red)".format(string)) plt.xlabel('Space') plt.grid(True) # if string == "DFEM": # plt.title("DFEM (blue) and CFEM (red)") # # plt.title("CFEM (red)") if self.nels == 64: plt.title("#Elem = 16 (red) and #Elem = 64 (green)") plt.show()
def Plot_Both(self, NumPts=10, string="CFEM"): """ plots CFEM solution to BVP (red) with analytic MMS solution (blue) """ plt.figure(1) if self.selection != 4 and string == "DFEM": xplot = linspace(self.bounds[0], self.bounds[1], 300) ref = zeros(len(xplot)) for i,x in enumerate(xplot): ref[i] = self.u(x) plt.plot(xplot, ref, linewidth = 2, color = 'green') for el in range(0, self.nels): xL = self.xnod[self.nod[el, 0]] xR = self.xnod[self.nod[el, self.order[el]-1]] dx = (xR - xL)/2.0 xpp = linspace(xL, xR, NumPts) xww = (xpp-xL)/dx - 1.0 ypp = zeros(NumPts) for j in range(0, NumPts): psi, dpsi = shape(xww[j], self.order[el]) uhval = 0.0 for k in range(0, self.order[el]): mynum = self.nod[el, k] uhval += self.soln[mynum]*psi[k] ypp[j] = uhval if string == "DFEM": plt.plot(xpp,ypp, ".-",linewidth=1, color = 'blue') else: plt.plot(xpp,ypp, ".-",linewidth=1, color = 'red') # plt.title("Exact solution (blue) and BVP {0} solution (red)".format(string)) plt.xlabel('Space') plt.grid(True) if string == "DFEM": plt.title("DFEM (blue) and CFEM (red)") plt.show()
def DFEM_1D(self): """ Solves a two-point BVP using Galerkin finite elements - automatically switches between continuous or discontinuous based on mesh it has access to """ nw, xw, w = QP(self.maxord) ## set up matrix and rhs of linear system self.stiff = zeros((self.nnodes, self.nnodes)) self.mass = zeros((self.nnodes, self.nnodes)) self.curr = zeros((self.nnodes, self.nnodes)) # "current" matrix used in DFEM (default to zeros for CFEM) self.rhsf = zeros( self.nnodes ) for el in range(0, self.nels): xL = self.xnod[self.nod[el, 0]] xR = self.xnod[self.nod[el, self.order[el]-1]] dx = (xR - xL)/2.0 # compute element stiffness matrix and rhs (load) vector k = zeros((self.order[el], self.order[el])) # element stiffness matrix m = zeros((self.order[el], self.order[el])) # element mass matrix f = zeros(self.order[el]) # element load vector for l in range(0, nw): # x runs in true element, xw runs in reference element x = xL + (1.0 + xw[l])*dx # calculations on ref element psi, dpsi = shape(xw[l], self.order[el]) Dval = self.D(x) SigAbs = self.SigA(x) fval = self.f(x) f += fval * psi * w[l]*dx k += Dval*outer(dpsi, dpsi)/dx/dx * w[l]*dx m += SigAbs*outer(psi, psi) * w[l]*dx # # uncomment to see the local (stiffness+mass) matrix and local load vector # print(k) # print(m) # print(f) # sys.exit() # neutron current, J, treatments for DFEM # current set up, only valid for linear FEs # - can make higher order FEs by generalizing if el == 0: self.Curr_iplus(el) elif el == self.nels-1: self.Curr_iminus(el) else: self.Curr_iminus(el) self.Curr_iplus(el) for idx in range(0, self.order[el]): self.rhsf[self.nod[el, idx]] += f[idx] for idy in range(0, self.order[el]): self.stiff[self.nod[el, idx], self.nod[el, idy]] += k[idx][idy] self.mass[self.nod[el, idx], self.nod[el, idy]] += m[idx][idy] # print("Writing Out Global Matrices") # cmat = open('CurrentMatrix.csv','w'); print(" current matrix") # mmat = open('MassMatrix.csv','w'); print(" mass matrix") # kmat = open('StiffMatrix.csv','w'); print(" stiffness matrix") # for idx in range(0, self.nnodes): # for idy in range(0, self.nnodes): # cmat.write("{0:.5e},".format(self.curr[idx, idy])) # mmat.write("{0:.5e},".format(self.mass[idx, idy])) # kmat.write("{0:.5e},".format(self.stiff[idx, idy])) # cmat.write("\n") # mmat.write("\n") # kmat.write("\n") # cmat.close() # mmat.close() # kmat.close() # print("Global RHS") # for i in range(0,self.nnodes): # print("{0:.3e} {1:.6e}".format(self.xnod[i], self.rhsf[i])) # sys.exit() self.soln = zeros(self.nnodes) mat = add(self.curr, add(self.stiff, self.mass)) # print("Writing Out Global Matrix") # gmat = open('GlobalMatrix.csv','w'); print(" global matrix") # for idx in range(0, self.nnodes): # for idy in range(0, self.nnodes): # gmat.write("{0:.5e},".format(mat[idx, idy])) # gmat.write("\n") # gmat.close() # sys.exit() if ((self.selection == 0) or (self.selection == 1) or (self.selection == 2) or (self.selection == 3) or (self.selection == 5)): self.soln[0] = self.u(self.bounds[0]) self.soln[-1] = self.u(self.bounds[-1]) subtract(self.rhsf, dot(mat, self.soln), out=self.rhsf) # used for non-zero Dirichlet BCs self.soln[1:-1] = linalg.solve(mat[1:-1, 1:-1], self.rhsf[1:-1]) elif self.selection == 6: # if Dirichlet boundary conditions eliminate known values from the system self.soln[0] = self.u(self.bounds[0]) subtract(self.rhsf, dot(mat, self.soln), out=self.rhsf) # used for non-zero Dirichlet BCs self.soln[1:] = linalg.solve(mat[1:, 1:], self.rhsf[1:]) else: self.soln = linalg.solve(mat, self.rhsf)
def CFEM_1D(self): """ Solves a two-point BVP using Galerkin finite elements - automatically switches between continuous or discontinuous based on mesh it has access to """ nw, xw, w = QP(self.maxord) ## set up matrix and rhs of linear system self.stiff = zeros((self.nnodes, self.nnodes)) self.mass = zeros((self.nnodes, self.nnodes)) self.rhsf = zeros( self.nnodes ) for el in range(0, self.nels): xL = self.xnod[self.nod[el, 0]] xR = self.xnod[self.nod[el, self.order[el]-1]] dx = (xR - xL)/2.0 # compute element stiffness matrix and rhs (load) vector k = zeros((self.order[el], self.order[el])) # element stiffness matrix m = zeros((self.order[el], self.order[el])) # element mass matrix f = zeros(self.order[el]) # element load vector for l in range(0, nw): # x runs in true element, xw runs in reference element x = xL + (1.0 + xw[l])*dx # calculations on ref element psi, dpsi = shape(xw[l], self.order[el]) Dval = self.D(x) SigAbs = self.SigA(x) fval = self.f(x) f += fval * psi * w[l]*dx k += Dval*outer(dpsi, dpsi)/dx/dx * w[l]*dx m += SigAbs*outer(psi, psi) * w[l]*dx # # uncomment to see the local (stiffness+mass) matrix and local load vector # print(k) # print(m) # print(f) # sys.exit() for idx in range(0, self.order[el]): self.rhsf[self.nod[el, idx]] += f[idx] for idy in range(0, self.order[el]): self.stiff[self.nod[el, idx], self.nod[el, idy]] += k[idx][idy] self.mass[self.nod[el, idx], self.nod[el, idy]] += m[idx][idy] self.soln = zeros(self.nnodes) mat = add(self.stiff, self.mass) # SOLVE! (for coefficients of finite elements, still not the \emph{actual} solution) if ((self.selection == 0) or (self.selection == 1) or (self.selection == 2) or (self.selection == 3) or (self.selection == 5)): # if Dirichlet boundary conditions eliminate known values from the system self.soln[0] = self.u(self.bounds[0]) self.soln[-1] = self.u(self.bounds[-1]) subtract(self.rhsf, dot(mat, self.soln), out=self.rhsf) # used for non-zero Dirichlet BCs self.soln[1:-1] = linalg.solve(mat[1:-1, 1:-1], self.rhsf[1:-1]) elif self.selection == 6: # if Dirichlet boundary conditions eliminate known values from the system self.soln[0] = self.u(self.bounds[0]) subtract(self.rhsf, dot(mat, self.soln), out=self.rhsf) # used for non-zero Dirichlet BCs self.soln[1:] = linalg.solve(mat[1:, 1:], self.rhsf[1:]) else: # if Reflecting BCs self.soln = linalg.solve(mat, self.rhsf)