Esempio n. 1
0
   def test_computeL1Error1D(self):
      # create mesh
      left = 2.5
      width = 1.5
      mesh = Mesh(3, width, x_start=left)

      # create "numerical solution" data
      numerical_solution = [(1.0,2.0),(1.6,2.2),(2.5,2.7)]

      # specify "exact solution" function
      def exact(x):
         return x**2 + 3.0

      # compute exact integral of difference
      exact_integral = 0.0
      for i in xrange(mesh.n_elems):
         # express local numerical solution as linear function y(x) = m*x + b
         el = mesh.getElement(i)
         xL = el.xl
         xR = el.xr
         yL = numerical_solution[i][0]
         yR = numerical_solution[i][1]
         dx = xR - xL
         dy = yR - yL
         m = dy / dx
         b = yL - xL*m

         # compute local integral of difference
         local_integral = (xR**3 - xL**3)/3.0 - 0.5*m*(xR**2 - xL**2)\
            + (3.0-b)*(xR - xL)
 
         # add to global integral of difference
         exact_integral += local_integral

      # compute numerical integral of difference
      numerical_integral = computeL1ErrorLD(mesh, numerical_solution, exact)

      # assert that numerical and exact integrals are approximately equal
      n_decimal_places = 14
      self.assertAlmostEqual(numerical_integral,exact_integral,n_decimal_places)
Esempio n. 2
0
   def test_DiffusionProblem(self):

      # number of elements
      n_elems = 50
      # mesh
      xL = 0.0             # left boundary of domain
      xR = 3.0             # right boundary of domain
      mesh = Mesh(n_elems,xR)
   
      # physics data
      sig_a = 0.25         # absorption cross section
      sig_s = 0.75         # scattering cross section
      sig_t = sig_s+sig_a  # total cross section
      D = 1.0/(3*sig_t)    # diffusion coefficient
      L = sqrt(D/sig_a)    # diffusion length
      Q = 1.0              # isotropic source
      rad_BC = RadBC(mesh, "dirichlet", psi_left=0.0, psi_right=0.0)
   
      # cross sections
      cross_sects = [(ConstantCrossSection(sig_s,sig_t),ConstantCrossSection(sig_s,sig_t))
         for i in xrange(n_elems)]
      # sources
      Q_iso  = [(0.5*Q) for i in xrange(mesh.n_elems*4)]
   
      # compute LD solution
      rad = radiationSolveSS(mesh,
                             cross_sects,
                             Q_iso,
                             rad_BC=rad_BC)

      # get continuous x-points
      xlist = makeContinuousXPoints(mesh)
   
      # function for exact scalar flux solution
      def exactScalarFlux(x):
         A = 2.4084787907
         B = -2.7957606046
         return A*sinh(x/L)+B*cosh(x/L)+Q*L*L/D
   
      # compute exact scalar flux solution at each x-point
      scalar_flux_exact = [exactScalarFlux(x) for x in xlist]

      # plot solutions
      if __name__ == '__main__':
         plotScalarFlux(mesh,rad.psim,rad.psip,scalar_flux_exact=scalar_flux_exact)
   
      # compute L1 error
      L1_error = computeL1ErrorLD(mesh,rad.phi,exactScalarFlux)
   
      # compute L1 norm of exact solution to be used as normalization constant
      L1_norm_exact = quad(exactScalarFlux, xL, xR)[0]

      # compute relative L1 error
      L1_relative_error = L1_error / L1_norm_exact

      # check that L1 error is small
      n_decimal_places = 3
      self.assertAlmostEqual(L1_relative_error,0.0,n_decimal_places)

      # check balance
      if __name__ == '__main__':
         bal = BalanceChecker(mesh, problem_type='rad_only', timestepper=None, dt=None)
         bal.computeSSRadBalance(0.0, 0.0, rad, sig_a, 0.5*Q)
Esempio n. 3
0
    def runConvergenceTest(self, time_stepper):

        # transient options
        dt_start = 0.01  # time step size
        t_start = 0.0  # start time
        t_end = 0.1  # end time

        # constant cross section values
        sig_s = 1.0
        sig_a = 2.0

        # boundary fluxes
        psi_left = 0.0
        psi_right = 0.0

        # compute exact scalar flux solution
        def exactScalarFlux(x):
            return t_end * sin(pi * x) + 2.0 * t_end * sin(pi * (1.0 - x))

        # create symbolic expressions for MMS solution
        x, t, alpha = sym.symbols('x t alpha')
        psim = 2 * t * sym.sin(sym.pi * (1 - x))
        psip = t * sym.sin(sym.pi * x)

        # number of elements
        n_elems = 10

        # number of refinement cycles
        n_cycles = 5

        # initialize lists for mesh size and L1 error for each cycle
        max_dx = list()
        L1_error = list()

        # print header
        if __name__ == '__main__':
            print('\n%s:' % time_stepper)

        # loop over refinement cycles
        for cycle in xrange(n_cycles):

            if __name__ == '__main__':
                print("\nCycle %d of %d: n_elems = %d" %
                      (cycle + 1, n_cycles, n_elems))

            # create uniform mesh
            mesh = Mesh(n_elems, 1.0)
            # append max dx for this cycle to list
            max_dx.append(mesh.max_dx)

            # radiation BC
            rad_BC = RadBC(mesh,
                           "dirichlet",
                           psi_left=psi_left,
                           psi_right=psi_right)

            # compute uniform cross sections
            cross_sects = [(ConstantCrossSection(sig_s, sig_s + sig_a),
                            ConstantCrossSection(sig_s, sig_s + sig_a))
                           for i in xrange(mesh.n_elems)]

            # create source function handles
            psim_src, psip_src = createMMSSourceFunctionsRadOnly(
                psim=psim, psip=psip, sigma_s_value=sig_s, sigma_a_value=sig_a)

            # IC
            n_dofs = mesh.n_elems * 4
            rad_IC = Radiation(np.zeros(n_dofs))

            # if run standalone, then be verbose
            if __name__ == '__main__':
                verbosity = 2
            else:
                verbosity = 0

            # run transient
            rad_new = runLinearTransient(mesh=mesh,
                                         time_stepper=time_stepper,
                                         dt_option='constant',
                                         dt_constant=dt_start,
                                         t_start=t_start,
                                         t_end=t_end,
                                         rad_BC=rad_BC,
                                         cross_sects=cross_sects,
                                         rad_IC=rad_IC,
                                         psim_src=psim_src,
                                         psip_src=psip_src,
                                         verbosity=verbosity)

            # compute L1 error
            L1_error.append(\
               computeL1ErrorLD(mesh, rad_new.phi, exactScalarFlux))

            # double number of elements for next cycle
            n_elems *= 2

        # compute convergence rates
        rates = computeConvergenceRates(max_dx, L1_error)

        # print convergence table if not being run in suite
        if __name__ == '__main__':
            printConvergenceTable(max_dx,
                                  L1_error,
                                  rates=rates,
                                  dx_desc='dx',
                                  err_desc='L1')

        # check that final rate is approximately 2nd order
        self.assert_(rates[n_cycles - 2] > 1.95)
Esempio n. 4
0
   def test_SSConvergence(self):

      # physics data
      sig_a = 0.25         # absorption cross section
      sig_s = 0.75         # scattering cross section
      sig_t = sig_s+sig_a  # total cross section
      D = 1.0/(3*sig_t)    # diffusion coefficient
      L = sqrt(D/sig_a)    # diffusion length
      xL = 0.0             # left boundary of domain
      xR = 3.0             # right boundary of domain
      Q = 1.0              # isotropic source
      A = 2.4084787907     # constant used in exact solution function
      B = -2.7957606046    # constant used in exact solution function
   
      # function for exact scalar flux solution
      def exactScalarFlux(x):
         return A*sinh(x/L) + B*cosh(x/L) + Q*L*L/D

      # number of elements
      n_elems = 10

      # number of refinement cycles
      n_cycles = 5

      # initialize lists for mesh size and L1 error for each cycle
      max_dx   = list()
      L1_error = list()

      # loop over refinement cycles
      for cycle in xrange(n_cycles):

         if __name__ == '__main__':
            print("Cycle %d of %d: n_elems = %d" % (cycle+1,n_cycles,n_elems))

         # mesh
         mesh = Mesh(n_elems,xR)
         # append max dx for this cycle to list
         max_dx.append(mesh.max_dx)
 
         # radiation BC
         rad_BC = RadBC(mesh, "dirichlet", psi_left=0.0, psi_right=0.0)
      
         # cross sections
         cross_sects = [(ConstantCrossSection(sig_s,sig_t),
                         ConstantCrossSection(sig_s,sig_t))
                         for i in xrange(n_elems)]

         # sources
         Q_iso  = [(0.5*Q) for i in xrange(mesh.n_elems*4)]
      
         # compute LD solution
         rad = radiationSolveSS(mesh,
                                cross_sects,
                                Q_iso,
                                rad_BC=rad_BC)
      
         # compute L1 error
         L1_error.append(\
            computeL1ErrorLD(mesh, rad.phi, exactScalarFlux))

         # double number of elements for next cycle
         n_elems *= 2

      # compute convergence rates
      rates = computeConvergenceRates(max_dx,L1_error)

      # print convergence table if not being run in suite
      if __name__ == '__main__':
         printConvergenceTable(max_dx,L1_error,rates=rates,
            dx_desc='dx',err_desc='L1')

      # check that final rate is approximately 2nd order
      self.assert_(rates[n_cycles-2] > 1.95)
Esempio n. 5
0
   def test_PureAbsorberProblem(self):

      # number of elements
      n_elems = 50
      # mesh
      L = 10.0       # domain length
      mesh = Mesh(n_elems,L)
   
      # physics data
      sig_t = 0.1    # total cross section
      sig_s = 0.0    # scattering cross section
      inc_minus = 10 # isotropic incoming angular flux for minus direction
      inc_plus  = 20 # isotropic incoming angular flux for plus  direction
      rad_BC    = RadBC(mesh, "dirichlet", psi_left=inc_plus, psi_right=inc_minus)
   
      # cross sections
      cross_sects = [(ConstantCrossSection(sig_s,sig_t),
                      ConstantCrossSection(sig_s,sig_t))
                      for i in xrange(n_elems)]
      # sources
      Q  = [0.0 for i in xrange(mesh.n_elems*4)]
   
      # compute LD solution
      rad = radiationSolveSS(mesh,
                             cross_sects,
                             Q,
                             rad_BC=rad_BC)
   
      # get continuous x-points
      xlist = makeContinuousXPoints(mesh)
   
      # exact solution functions
      def exactPsiMinus(x):
         return inc_minus*exp(-sig_t/mu["-"]*(x-L))
      def exactPsiPlus(x):
         return inc_plus *exp(-sig_t/mu["+"]*x)
      def exactScalarFlux(x):
         return exactPsiMinus(x) + exactPsiPlus(x)

      # compute exact solutions
      psim_exact = [exactPsiMinus(x) for x in xlist]
      psip_exact = [exactPsiPlus(x)  for x in xlist]
      exact_scalar_flux = [psi_m+psi_p for psi_m, psi_p
         in zip(psim_exact, psip_exact)]

      # plot solutions
      if __name__ == '__main__':
         plotAngularFlux(mesh, rad.psim, rad.psip,
            psi_minus_exact=psim_exact, psi_plus_exact=psip_exact)

      # compute L1 error
      L1_error = computeL1ErrorLD(mesh,rad.phi,exactScalarFlux)
   
      # compute L1 norm of exact solution to be used as normalization constant
      L1_norm_exact = quad(exactScalarFlux, 0.0, L)[0]

      # compute relative L1 error
      L1_relative_error = L1_error / L1_norm_exact

      # check that L1 error is small
      n_decimal_places = 3
      self.assertAlmostEqual(L1_relative_error,0.0,n_decimal_places)
    def test_PureScatteringProblem(self):

        # physics data
        sig_a = 0.0  # absorption cross section
        sig_s = 1.0  # scattering cross section
        sig_t = sig_s + sig_a  # total cross section
        xL = 0.0  # left boundary of domain
        width = 100.0  # domain width
        xR = xL + width  # right boundary of domain
        inc_j_minus = 1  # incoming minus direction half-range current
        inc_j_plus = 3  # incoming plus  direction half-range current
        Q = 1.0  # isotropic source
        D = 1.0 / (3 * sig_t)  # diffusion coefficient

        # number of elements
        n_elems = 50
        # mesh
        mesh = Mesh(n_elems, width, xL)

        # radiation BC
        rad_BC = RadBC(mesh,
                       "dirichlet",
                       psi_left=2 * inc_j_plus,
                       psi_right=2 * inc_j_minus)

        # cross sections
        cross_sects = [(ConstantCrossSection(sig_s, sig_t),
                        ConstantCrossSection(sig_s, sig_t))
                       for i in xrange(n_elems)]
        # sources
        Q_src = [0.5 * Q for i in xrange(mesh.n_elems * 4)]

        # compute LD solution
        rad = radiationSolveSS(mesh, cross_sects, Q_src, rad_BC=rad_BC)

        # get continuous x-points
        xlist = makeContinuousXPoints(mesh)

        # function for the exact scalar flux solution
        def exactScalarFlux(x):
            return Q / (2 * D) * (2 * D * xR + xR * x - x * x)

        # compute exact scalar flux solution
        scalar_flux_exact = [exactScalarFlux(x) for x in xlist]

        # plot solutions
        if __name__ == '__main__':
            plotScalarFlux(mesh,
                           rad.psim,
                           rad.psip,
                           scalar_flux_exact=scalar_flux_exact)

        # compute L1 error
        L1_error = computeL1ErrorLD(mesh, rad.phi, exactScalarFlux)

        # compute L1 norm of exact solution to be used as normalization constant
        L1_norm_exact = quad(exactScalarFlux, xL, xR)[0]

        # compute relative L1 error
        L1_relative_error = L1_error / L1_norm_exact

        # check that L1 error is small
        n_decimal_places = 2
        self.assertAlmostEqual(L1_relative_error, 0.0, n_decimal_places)
Esempio n. 7
0
    def test_SSConvergence(self):

        # physics data
        sig_a = 0.25  # absorption cross section
        sig_s = 0.75  # scattering cross section
        sig_t = sig_s + sig_a  # total cross section
        D = 1.0 / (3 * sig_t)  # diffusion coefficient
        L = sqrt(D / sig_a)  # diffusion length
        xL = 0.0  # left boundary of domain
        xR = 3.0  # right boundary of domain
        Q = 1.0  # isotropic source
        A = 2.4084787907  # constant used in exact solution function
        B = -2.7957606046  # constant used in exact solution function

        # function for exact scalar flux solution
        def exactScalarFlux(x):
            return A * sinh(x / L) + B * cosh(x / L) + Q * L * L / D

        # number of elements
        n_elems = 10

        # number of refinement cycles
        n_cycles = 5

        # initialize lists for mesh size and L1 error for each cycle
        max_dx = list()
        L1_error = list()

        # loop over refinement cycles
        for cycle in xrange(n_cycles):

            if __name__ == '__main__':
                print("Cycle %d of %d: n_elems = %d" %
                      (cycle + 1, n_cycles, n_elems))

            # mesh
            mesh = Mesh(n_elems, xR)
            # append max dx for this cycle to list
            max_dx.append(mesh.max_dx)

            # radiation BC
            rad_BC = RadBC(mesh, "dirichlet", psi_left=0.0, psi_right=0.0)

            # cross sections
            cross_sects = [(ConstantCrossSection(sig_s, sig_t),
                            ConstantCrossSection(sig_s, sig_t))
                           for i in xrange(n_elems)]

            # sources
            Q_iso = [(0.5 * Q) for i in xrange(mesh.n_elems * 4)]

            # compute LD solution
            rad = radiationSolveSS(mesh, cross_sects, Q_iso, rad_BC=rad_BC)

            # compute L1 error
            L1_error.append(\
               computeL1ErrorLD(mesh, rad.phi, exactScalarFlux))

            # double number of elements for next cycle
            n_elems *= 2

        # compute convergence rates
        rates = computeConvergenceRates(max_dx, L1_error)

        # print convergence table if not being run in suite
        if __name__ == '__main__':
            printConvergenceTable(max_dx,
                                  L1_error,
                                  rates=rates,
                                  dx_desc='dx',
                                  err_desc='L1')

        # check that final rate is approximately 2nd order
        self.assert_(rates[n_cycles - 2] > 1.95)