Ejemplo n.º 1
0
def test_empty_texts():
    assert str(Elem(content=Text(''))) == '<div></div>'
    assert str(Elem(content=[Text(''), Text('')])) == '<div></div>'
    assert str(
        Elem(content=[Text('foo'), Text(''), Elem()])) == '<div>\n  foo\
\n  <div></div>\n</div>'

    print('Elem with empty texts : OK.')
Ejemplo n.º 2
0
def test_embedding():
    assert (str(Elem(content=Elem(content=Elem(content=Elem())))) == """<div>
  <div>
    <div>
      <div></div>
    </div>
  </div>
</div>""")
    print('Element embedding : OK.')
Ejemplo n.º 3
0
 def __init__(self, mat_cls, mesh_cls, prob_dict):
     # equation name
     self._name = 'nda'
     # mesh data
     self._mesh = mesh_cls
     self._cell_length = mesh_cls.cell_length()
     # quantities of interest
     self._keff = 1.0
     self._keff_prev = 1.0
     # preassembly-interpolation data
     self._elem = Elem(self._cell_length)
     # material ids and group info
     self._mids = mat_cls.get('ids')
     self._n_grp = mat_cls.get('n_grps')
     self._g_thr = mat_cls.get('g_thermal')
     # mesh
     self._mesh = msh_cls
     # problem type
     self._is_eigen = prob_dict['is_eigen_problem']
     self._do_ua = prob_dict['do_ua']
     # linear algebra objects
     self._sys_mats = {}
     self._sys_rhses = {
         k: np.ones(self._n_dof)
         for k in xrange(self._n_tot)
     }
     self._fixed_rhses = {
         k: np.zeros(self._n_dof)
         for k in xrange(self._n_tot)
     }
     self._sflxes = {k: np.ones(self._n_dof) for k in xrange(self._n_grp)}
     # linear solver objects
     self._lu = {}
     # total number of components: keep consistency with HO
     self._n_tot = self._n_grp
     # all material
     self._dcoefs = mat_cls.get('diff_coef')
     self._sigts = mat_cls.get('sig_t')
     self._sigses = mat_cls.get('sig_s')
     self._sigrs = mat_cls.get('sig_r')
     self._fiss_xsecs = mat_cls.get('chi_nu_sig_f')
     # derived material properties
     self._sigrs_ua = mat_cls.get('sig_r_ua')
     self._dcoefs_ua = mat_cls.get('diff_coef_ua')
     # fission source
     self._global_fiss_src = self._calculate_fiss_src()
     self._global_fiss_src_prev = self._global_fiss_src
     # assistance object
     self._local_dof_pairs = pd(xrange(4), xrange(4))
Ejemplo n.º 4
0
def last_test():
    assert (str(
        Elem(tag='html',
             content=[
                 Elem(tag='head',
                      content=Elem(tag='title',
                                   content=Text('"Hello ground!"'))),
                 Elem(tag='body',
                      content=[
                          Elem(tag='h1', content=Text('"Oh no, not again!"')),
                          Elem(tag='img',
                               attr={'src': "http://i.imgur.com/pfp3T.jpg"},
                               tag_type='simple')
                      ])
             ])) == """<html>
  <head>
    <title>
      "Hello ground!"
    </title>
  </head>
  <body>
    <h1>
      "Oh no, not again!"
    </h1>
    <img src="http://i.imgur.com/pfp3T.jpg" />
  </body>
</html>""")
    print('Last Test : OK.')
Ejemplo n.º 5
0
def last_test():
    print(
        str(
            Elem(tag='html',
                 content=[
                     Elem(tag='head',
                          content=Elem(tag='title',
                                       content=Text('"Hello ground!"'))),
                     Elem(tag='body',
                          content=[
                              Elem(tag='h1',
                                   content=Text('"Oh no, not again!"')),
                              Elem(
                                  tag='img',
                                  attr={'src': "http://i.imgur.com/pfp3T.jpg"},
                                  tag_type='simple')
                          ])
                 ])))
    # == '''<html>
    #   <head>
    #     <title>
    #       "Hello ground!"
    #     </title>
    #   </head>
    #   <body>
    #     <h1>
    #       "Oh no, not again!"
    #     </h1>
    #     <img src="http://i.imgur.com/pfp3T.jpg"/>
    #   </body>
    # </html>'''
    #    )
    print('Last Test : OK.')
Ejemplo n.º 6
0
def test_elem_basics():
    # Default behaviour :
    assert str(Elem()) == '<div></div>'
    # Arguments order :
    assert str(Elem('div', {}, None, 'double')) == '<div></div>'
    # Argument names :
    assert str(Elem(tag='body', attr={}, content=Elem(),
                    tag_type='double')) == '<body>\n  <div></div>\n</body>'
    # With elem as content :
    assert str(Elem(content=Elem())) == '<div>\n  <div></div>\n</div>'
    # With list as content :
    assert str(Elem(content=[Text('foo'), Text('bar'), Elem()])) == '<div>\n  foo\n  bar\n \
 <div></div>\n</div>'
    print('Basic Elem behaviour : OK.')
    def __init__(self, n: int, view: 'View'):
        self.view = view
        sorted_array = []
        for i in range(1, n + 1):
            sorted_array.append(i)

        self.array = []

        for i in range(0, n):
            rand_elem = random.choice(sorted_array)
            sorted_array.remove(rand_elem)
            self.array.append(Elem(rand_elem, self))

        self.high_lighted1 = -1
        self.high_lighted2 = -1
        self.comparisons = 0
        self.mutations = 0
Ejemplo n.º 8
0
def test_errors():
    # Type error if the content isn't made of Text or Elem.
    try:
        Elem(content=1)
    except Exception as e:
        assert type(e) == Elem.ValidationError
    # The right way :
    assert str(Elem(content=Text(1))) == '<div>\n  1\n</div>'

    # Type error if the elements of the list aren't Text or Elem instances.
    try:
        Elem(content=['foo', Elem(), 1])
    except Exception as e:
        assert type(e) == Elem.ValidationError
    # The right way :
    assert (str(
        Elem(content=[Text('foo'), Elem(), Text(1)])) ==
            '<div>\n  foo\n  <div></div>\n  1\n</div>')

    # Same with add_method()
    try:
        elem = Elem()
        elem.add_content(1)
        raise (Exception("incorrect behaviour."))
    except Exception as e:
        assert isinstance(e, Elem.ValidationError)

    # Or with lists :
    try:
        elem = Elem()
        elem.add_content([
            1,
        ])
        raise (Exception('incorrect behaviour'))
    except Exception as e:
        assert isinstance(e, Elem.ValidationError)

    # str can't be used :
    try:
        elem = Elem()
        elem.add_content([
            '',
        ])
        raise (Exception("incorrect behaviour."))
    except Exception as e:
        assert isinstance(e, Elem.ValidationError)

    try:
        elem = Elem(content='')
        raise (Exception("incorrect behaviour."))
    except Exception as e:
        assert isinstance(e, Elem.ValidationError)
    print('Error cases : OK.')
Ejemplo n.º 9
0
 def __init__(self, content=None, attr={}):
     Elem.__init__(self,
                   tag="ul",
                   attr=attr,
                   content=content,
                   tag_type='double')
Ejemplo n.º 10
0
 def __init__(self, content=None, attr={}):
     Elem.__init__(self,
                   tag="img",
                   attr=attr,
                   content=content,
                   tag_type='simple')
Ejemplo n.º 11
0
class NDA(object):
    def __init__(self, mat_cls, mesh_cls, prob_dict):
        # equation name
        self._name = 'nda'
        # mesh data
        self._mesh = mesh_cls
        self._cell_length = mesh_cls.cell_length()
        # quantities of interest
        self._keff = 1.0
        self._keff_prev = 1.0
        # preassembly-interpolation data
        self._elem = Elem(self._cell_length)
        # material ids and group info
        self._mids = mat_cls.get('ids')
        self._n_grp = mat_cls.get('n_grps')
        self._g_thr = mat_cls.get('g_thermal')
        # mesh
        self._mesh = msh_cls
        # problem type
        self._is_eigen = prob_dict['is_eigen_problem']
        self._do_ua = prob_dict['do_ua']
        # linear algebra objects
        self._sys_mats = {}
        self._sys_rhses = {
            k: np.ones(self._n_dof)
            for k in xrange(self._n_tot)
        }
        self._fixed_rhses = {
            k: np.zeros(self._n_dof)
            for k in xrange(self._n_tot)
        }
        self._sflxes = {k: np.ones(self._n_dof) for k in xrange(self._n_grp)}
        # linear solver objects
        self._lu = {}
        # total number of components: keep consistency with HO
        self._n_tot = self._n_grp
        # all material
        self._dcoefs = mat_cls.get('diff_coef')
        self._sigts = mat_cls.get('sig_t')
        self._sigses = mat_cls.get('sig_s')
        self._sigrs = mat_cls.get('sig_r')
        self._fiss_xsecs = mat_cls.get('chi_nu_sig_f')
        # derived material properties
        self._sigrs_ua = mat_cls.get('sig_r_ua')
        self._dcoefs_ua = mat_cls.get('diff_coef_ua')
        # fission source
        self._global_fiss_src = self._calculate_fiss_src()
        self._global_fiss_src_prev = self._global_fiss_src
        # assistance object
        self._local_dof_pairs = pd(xrange(4), xrange(4))

    def name(self):
        return self._name

    def assemble_bilinear_forms(self, ho_cls=None, correction=False):
        '''@brief A function used to assemble bilinear forms of NDA for current
        iterations

        @param correction A boolean used to determine if correction terms are
        assembled. By default, it's not. In this case, the bilinear form is typical
        diffusion
        '''
        # TODO: Boundary is assumed to be reflective so kappa will not be handled
        streaming, mass = self._elem.streaming(), self._elem.mass()
        if correction:
            assert ho_cls is not None, 'ho_cls has to be filled in for NDA correction'
        # basic diffusion Elementary matrices
        diff_mats = {}
        # Elementary correction matrices
        corx, cory, sigt, dcoef = self._elem.corx(), self._elem.cory(), 0, 0
        for g in xrange(self._n_grp):
            self._sys_mats[g] = sps.lil_matrix(
                (self._mesh.n_node(), self._mesh.n_node()))
            for mid in self._mids:
                sigt, sigr, dcoef = self._sigts[mid][g], self._sigrs[mid][
                    g], self._dcoefs[mid][g]
                diff_mats[(g, mid)] = (dcoef * streaming + sigr * mass)
        # preassembled matrices for upscattering acceleration
        if self._do_ua:
            self._sys_mats['ua'] = sps.lil_matrix(
                (self._mesh.n_node(), self._mesh.n_node()))
            for mid in self._mids:
                dcoef_ua, sigr_ua = self._dcoefs_ua[mid], self._sigrs_ua[mid]
                # basic elementary diffusion matrices for upscattering acceleration
                diff_mats[('ua',
                           mid)] = (dcoef_ua * streaming + sigr_ua * mass)

        # loop over cells for assembly
        for cell in self._mesh.cells():
            # get global dof index and mat id
            idx, mid = cell.id(), cell.global_idx()
            # corrections for all groups in current cell and ua
            corr_vecs = {}
            if correction:
                corr_vecs = ho_cls.calculate_nda_cell_correction(mat_id=mid,
                                                                 idx=idx)
            for g in xrange(self._n_grp):
                # if correction is asked
                cor_mat = np.zeros((4, 4))
                if correction:
                    # calculate NDA correction in HO class
                    corr_vecs[g] = ho_cls.calculate_nda_cell_correction(
                        g=g, mat_id=mid, idx=idx)
                    # TODO: fixed the "9"
                    for i in xrange(9):
                        # x-component
                        cor_mat += corr_vecs['x_comp'][g][i] * corx[i]
                        # y-component
                        cor_mat += corr_vecs['x_comp'][g][i] * cory[i]
                    diff_mats[(g, mid)] += cor_mat
                # assemble global system
                for ci, cj in self._local_dof_pairs:
                    self._sys_mats[g][idx[ci],
                                      idx[cj]] += diff_mats[(g, mid)][ci, cj]

            # if we do upscattering acceleration
            if self._do_ua:
                # assemble global system of ua matrix without correction
                for ci, cj in self._local_dof_pairs:
                    self._sys_mats['ua'][idx[ci],
                                         idx[cj]] += diff_mats[('ua', mid)][ci,
                                                                            cj]

                # correction matrix for upscattering acceleration
                cor_mat_ua = np.zeros((4, 4))
                if correction:
                    for i in xrange(len(corr_vecs[0])):
                        cor_mat_ua += (corr_vecs['x_ua'][i] * corx[i] +
                                       corr_vecs['y_ua'][i] * cory[i])
                        diff_mats[('ua', mid)] += cor_mat_ua[ci, cj]
                # mapping UA matrix to global
                for ci, cj in self._local_dof_pairs:
                    self._sys_mats['ua'][idx[ci],
                                         idx[cj]] += diff_mats[('ua', mid)][ci,
                                                                            cj]

        # Transform system matrices to CSC format
        for g in xrange(self._n_grp):
            self._sys_mats[g] = sps.csc_matrix(self._sys_mats[g])
        if self._do_ua:
            self._sys_mats['ua'] = sps.csc_matrix(self._sys_mats['ua'])

    def assemble_fixed_linear_forms(self, sflxes_prev=None):
        '''@brief  function used to assemble linear form for fixed source or fission
        source
        '''
        # scale the fission xsec by keff
        scaled_fiss_xsec = {k: v / self._keff for k, v in self._fiss_xsecs}
        for g in xrange(self._n_grp):
            fixed_rhses[g] = np.array(self._mesh.n_node())
            for cell in self._mesh.cells():
                idx, mid, fiss_src = cell.global_idx(), cell.id(), np.zeros(4)
                for gi in filter(lambda: scaled_fiss_xsec[mid][g, x] > 1.0e-14,
                                 xrange(self._n_grp)):
                    sflx_vtx = self._sflxes[g][idx] if not sflxes_prev else \
                               sflxes_prev[g][idx]
                    fiss_src += scaled_fiss_xsec[mid][g, gi] * np.dot(
                        mass, sflx_vtx)
                self._fixed_rhses[g][idx] += fiss_src

    def _assemble_group_linear_forms(self, g):
        '''@brief A function used to assemble linear form for upscattering acceleration
        '''
        # NOTE: due to pass-by-reference feature in Python, we have to make
        # deep copy of fixed rhs instead of using "="
        np.copyto(self._sys_rhses[g], self._fixed_rhses[g])
        # get mass matrix
        mass = self._elem.mass()
        for cell in mesh.cells:
            idx, mid = cell.global_idx(), cell.id()
            sigs = self._sigses[mid][g, :]
            scat_src = np.zeros(4)
            for gi in filter(lambda x: sigs[x] > 1.0e-14 and x != g,
                             xrange(self._n_grp)):
                sflx_vtx = self._sflxes[gi][idx]
                scat_src += sigs[gi] * np.dot(mass, sflx_vtx)
            self._sys_rhses[g][idx] += scat_src

    def _assemble_ua_linear_form(self, sflxes_old):
        '''@brief A function used to assemble linear form for upscattering acceleration
        '''
        assert len(sflxes_old)==self._n_grp, \
        'old scalar fluxes should have the same number of groups as current scalar fluxes'
        mass = self._elem.mass()
        self._sys_rhses['ua'] *= 0.0
        for cell in self._mesh.cells():
            idx, mid, scat_src_ua = cell.global_idx(), cell.id(), np.zeros(4)
            for g in xrange(self._g_thr, self._n_grp - 1):
                for gi in xrange(g + 1, self._n_grp):
                    sigs = self._sigses[mid][g, gi]
                    if sigs > 1.0e-14:
                        dsflx_vtx = self._sflxes[gi][idx] - sflxes_old[g][idx]
                        scat_src_ua += sigs * np.dot(mass, dsflx_vtx)
            self._sys_rhses['ua'][idx] += scat_src_ua

    def solve_in_group(self, g):
        assert 0 <= g < self._n_grp, 'Group index out of range'
        self._assemble_group_linear_forms(g)
        if g not in self._lu:
            # factorize it if not yet
            self._lu[g] = sla.splu(self._sys_mats[g])
        # direct solve
        self._sflxes[g] = self._lu[g].solve(self._sys_rhses[g])

    #NOTE: this function has to be removed if abstract class is implemented
    def calculate_keff(self):
        assert not self._is_eigen, 'only be called in eigenvalue problems'
        # update the previous fission source and previous keff
        self._global_fiss_src_prev, self._keff_prev = self._global_fiss_src, self._keff
        # calculate the new fission source
        self._calculate_fiss_src()
        # calculate the new keff
        self._keff = self._keff_prev * self._global_fiss_src / self._global_fiss_src_prev
        return self._keff

    #NOTE: this function has to be removed if abstract class is implemented
    def calculate_sflx_diff(self, sflxes_old, g):
        '''@brief function used to generate ho scalar flux for Group g using
        angular fluxes

        @param sflx_old Scalar flux from previous generation
        @param g The group index
        @return double The relative difference between new and old scalar flux
        '''
        # return the l1 norm relative difference
        return norm(
            (self._sflxes[g] - sflxes_old[g]), 1) / norm(self._sflxes[g], 1)

    #NOTE: this function has to be removed if abstract class is implemented
    def update_sflxes(self, sflxes_old, g):
        '''@brief A function used to update scalar flux for group g

        @param sflxes_old A dictionary
        @param g Group index
        '''
        np.copyto(sflxes_old[g], self._sflxes[g])

    def update_ua(self):
        '''@brief A function used to update the scalar fluxes after upscattering
        acceleration
        '''
        for g in xrange(self.g_thr, self._n_grp):
            self._sflxes[g] += self._sflxes['ua']

    def clear_factorization(self):
        '''@brief A function used to clear all the factorizations after NDA is dictionaries
        for current iteration

        Every outer iterations, NDA equations are modified so previous factorizations
        are no longer suitable and must be cleared and redone.
        '''
        self._lu.clear()

    def solve_ua(self):
        # assemble ua
        self._assemble_ua_linear_form()
        if 'ua' not in self._lu:
            # factorize it if not yet
            self._lu['ua'] = sla.splu(self._sys_mats['ua'])
        # direct solve
        self._sflxes['ua'] = self._lu['ua'].solve(self._sys_rhses['ua'])

    def get_sflxes(self, g):
        '''@brief Function called outside to retrieve the scalar flux value for Group g

        @param g Target group number
        '''
        return self._sflxes[g]

    def get_sflx_vtx(self, g, idx):
        return self._sflxes[g][idx]

    def get_keff(self):
        '''@brief A function used to retrieve keff

        @return keff calculated in SAAF class
        '''
        return self._keff

    def do_ua(self):
        return self._do_ua

    def n_dof(self):
        return self._mesh.n_node()

    def n_grp(self):
        return self._n_grp
Ejemplo n.º 12
0
class SAAF(object):
    def __init__(self, mat_cls, mesh_cls, prob_dict):
        # name of the Equation
        self._name = 'saaf'
        # mesh data
        self._mesh = mesh_cls
        self._cell_length = mesh_cls.cell_length()
        # quantities of interest
        self._keff = 1.0
        self._keff_prev = 1.0
        # preassembly-interpolation data
        self._elem = Elem(self._cell_length)
        # material data
        self._n_grp = mat_cls.get('n_grps')
        self._g_thr = mat_cls.get('g_thermal')
        self._sigts = mat_cls.get('sig_t')
        self._isigts = mat_cls.get('inv_sig_t')
        self._fiss_xsecs = mat_cls.get_per_str('chi_nu_sig_f')
        self._nu_sigfs = mat_cls.get('nu_sig_f')
        self._sigses = mat_cls.get_per_str('sig_s')
        self._dcoefs = mat_cls.get('diff_coef')
        self._mids = mat_cls.ids()
        # derived material data
        self._ksi_ua = mat_cls.get('ksi_ua')
        # problem type: is problem eigenvalue problem
        # aq data in forms of dictionary
        self._aq = AQ(prob_dict['sn_order']).get_aq_data()
        self._n_dir = self._aq['n_dir']
        # total number of components in HO
        self._n_tot = self._n_grp * self._n_dir
        # get a component indexing mapping
        self._comp = dict()
        # component to group map
        self._comp_grp = dict()
        # component to direction map
        self._comp_dir = dict()
        self._generate_component_map()
        # local vectors
        self._rhs_mats = dict()
        self._preassembly_rhs()
        # related to global matrices and vectors
        self._n_dof = mesh_cls.n_node()
        self._sys_mats = {}
        # be very careful about the following
        self._sys_rhses = {
            k: np.ones(self._n_dof)
            for k in xrange(self._n_tot)
        }
        self._fixed_rhses = {
            k: np.zeros(self._n_dof)
            for k in xrange(self._n_tot)
        }
        self._aflxes = {k: np.ones(self._n_dof) for k in xrange(self._n_tot)}
        # scalar flux for current calculation
        self._sflxes = {k: np.ones(self._n_dof) for k in xrange(self._n_grp)}
        # linear solver objects
        self._lu = {}
        # source iteration tol
        self._tol = 1.0e-7
        # fission source
        self._global_fiss_src = self._calculate_fiss_src()
        self._global_fiss_src_prev = self._global_fiss_src
        # assistance:
        self._local_dof_pairs = pd(xrange(4), xrange(4))

    def _generate_component_map(self):
        '''@brief Internal function used to generate mappings between component,
        group and directions
        '''
        ct = 0
        for g in xrange(self._n_grp):
            for d in xrange(self._n_dir):
                self._comp[(g, d)] = ct
                self._comp_grp[ct] = g
                self._comp_dir[ct] = d
                ct += 1

    def _preassembly_rhs(self):
        for mid in self._mids:
            sigts, isigts = self._sigts[mid], self._isigts[mid]
            for g in xrange(self._n_grp):
                for d in xrange(self._n_dir):
                    ox, oy = self._aq['omega'][d]
                    # streaming part of rhs
                    rhs_mat = (ox * self._elem.dxvu() +
                               oy * self._elem.dyvu()) * isigts[g]
                    # mass part of rhs
                    rhs_mat += sigts[g] * self._elem.mass()
                    self._rhs_mats[mid] = {(g, d): rhs_mat}

    def name(self):
        return self._name

    def assemble_bilinear_forms(self):
        '''@brief Function used to assemble bilinear forms

        @param correction Boolean to determine if correction is needed. Only useful
        in NDA class
        '''
        # retrieve all the material properties
        for i in xrange(self._n_tot):
            # get the group and direction indices
            g, d = self._comp_grp[i], self._comp_dir[i]
            # get omega_i * omega_j combinations
            oxox, oxoy, oyoy = self._aq['dir_prods'][d].values()
            # dict containing lhs local matrices for all materials for component i
            lhs_mats = dict()
            for mid in self._mids:
                sigt, isigt = self._sigts[mid][g], self._isigts[mid][g]
                # streaming lhs
                matx = isigt * (oxox * self._elem.dxdx() + oxoy *
                                (self._elem.dxdy() + self._elem.dydx()) +
                                oyoy * self._elem.dydy())
                # collision matrix
                matx += sigt * self._elem.mass()
                lhs_mats[mid] = matx
            # loop over cells for assembly
            # sys_mat: temp variable for system matrix for one component
            sys_mat = sps.lil_matrix(
                (self._mesh.n_node(), self._mesh.n_node()))
            for cell in self._mesh.cells():
                # retrieving global indices and material id per cell
                idx, mid = cell.global_idx(), cell.get('id')
                # mapping local matrices to global
                for ci, cj in self._local_dof_pairs:
                    sys_mat[idx[ci], idx[cj]] += lhs_mats[mid][ci][cj]
                # boundary part
                if cell.bounds():
                    # loop over
                    for bd in cell.bounds().keys():
                        if self._aq['bd_angle'][(bd, d)] > 0:
                            #outgoing boundary assembly: retrieving omega*n and boundary mass matrices
                            odn, bd_mass = self._aq['bd_angle'][(
                                bd, d)], self._elem.bdmt()[bd]
                            # mapping local vertices to global
                            for ci, cj in self._local_dof_pairs:
                                if bd_mass[ci][cj] > 1.0e-14:
                                    sys_mat[idx[ci],
                                            idx[cj]] += odn * bd_mass[ci][cj]

            # transform lil_matrix to csc_matrix for efficient computation
            self._sys_mats[i] = sps.csc_matrix(sys_mat)

    def assemble_fixed_linear_forms(self, sflxes_prev=None, nda_cls=None):
        '''@brief a function used to assemble fixed source or fission source on the
        rhs for all components

        Generate fission source. If nda_cls is not None, sflxes_prev is ignored
        '''
        if not nda_cls:
            assert sflxes_prev is not None, 'scalar flux must be provided'
        # get properties per str scaled by keff
        for cp in xrange(self._n_tot):
            # re-init fixed rhs. This must be done at the beginning of calling this function
            self._fixed_rhses[cp] = np.array(self._n_dof)
            # get group and direction indices
            g, d = self._comp_grp[cp], self._comp_dir[cp]
            for cell in self._mesh.cells():
                idx, mid = cell.global_idx(), cell.get('id')
                fiss_src, fiss_xsec = np.zeros(4), self._fiss_xsecs[mid][g]
                # get fission source contribution from ingroups
                for gi in filter(lambda j: fiss_xsec[j] > 1.0e-14,
                                 xrange(self._n_grp)):
                    sflx_vtx = sflxes_prev[gi][idx] if not nda_cls else \
                               nda_cls.get_sflx_vtx(gi, idx)
                    fiss_src += fiss_xsec[gi] * np.dot(
                        self._rhs_mats[mid][(g, d)], sflx_vtx)
                self._fixed_rhses[cp][idx] += fiss_src

    def _assemble_group_linear_forms(self, g, nda_cls=None):
        '''@brief Function used to assemble linear forms for Group g

        if NDA is used, nda_cls must be filled in. This function will not be called
        from outside. It will rather be called in solve_in_group or solve_all_groups
        '''
        assert 0 <= g < self._n_grp, 'Group index out of range'
        if nda_cls:
            assert nda_cls.name(
            ) == 'nda', 'Correct NDA class must be filled in'
        for d in xrange(self._n_dir):
            cp = self._comp[(g, d)]
            # get fixed/fission source
            # NOTE: due to pass-by-reference feature in Python, we have to make
            # deep copy of fixed rhs instead of using "="
            np.copyto(self._sys_rhses[cp], self._fixed_rhses[cp])
            # go through all cells
            for cell in self._mesh.cells():
                # get global dof indices and material ids
                idx, mid = cell.global_idx(), cell.get('id')
                # get scattering matrix for current cell
                sigs = self._sigses[mid]
                # calculate local scattering source
                scat_bd_src = np.zeros(4)
                for gi in filter(lambda x: sigs[g][x] > 1.0e-14,
                                 xrange(self._n_grp)):
                    # retrieve scalar flux at vertices
                    sflx_vtx = self._sflxes[gi][idx] if not nda_cls \
                    else nda_cls.get_sflx_vtx(gi, idx)
                    # calculate scattering source
                    scat_bd_src += sigs[g, gi] * np.dot(
                        self._rhs_mats[mid][(g, d)], sflx_vtx)
                # if it's boundary
                if cell.bounds():
                    for bd, tp in cell.bounds().items():
                        # incident boundary with reflective setting
                        if tp == 'refl' and self._aq['bd_angle'][(bd,
                                                                  d)] < 0.0:
                            r_dir = self._aq['refl_dir'][(bd, d)]
                            odn = abs(self._aq['bd_angle'][(bd, d)])
                            bd_mass = self._elem.bdmt()[bd]
                            bd_aflx = self._aflxes[self._comp(g, r_dir)][idx]
                            scat_bd_src += odn * np.dot(bd_mass, bd_aflx)
                self._sys_rhses[cp][idx] += scat_bd_src

    def _assemble_linear_forms(self, nda_cls):
        '''@brief A function call to assemble linear forms for all components once

        This function is to be called along with NDA providing keff and fluxes
        '''
        assert nda_cls is not None and nda_cls.name(
        ) == 'nda', 'NDA has to be passed in to call'
        # NOTE: this is not the most efficient way as there is no need to separating
        # the assembly process here
        self.assemble_fixed_linear_forms(sflxes_prev=None, nda_cls=nda_cls)
        for g in xrange(self._n_grp):
            self._assemble_group_linear_forms(g=g, nda_cls=nda_cls)

    def solve_all_groups(self, nda_cls):
        '''@brief A function call to solve all components once

        This function is to be called along with NDA providing rhs
        '''
        self._assemble_linear_forms(nda_cls=nda_cls)
        for i in xrange(self._n_tot):
            if i not in self._lu:
                # factorization
                self._lu[i] = sla.splu(self._sys_mats[comp[(g, d)]])
            # direct solve for angular fluxes
            self._aflxes[i] = self._lu[i].solve(self._sys_rhses[i])

    def solve_in_group(self, g):
        '''@brief Called to solve direction by direction inside Group g

        @param g Group index
        '''
        assert 0 <= g < self._n_grp, 'Group index out of range'
        # Source iteration
        e, sflx_ig_prev = 1.0, np.ones(self._n_dof)
        while e > self._tol:
            # assemble group rhses
            self._assemble_group_linear_forms(g)
            # copy scalar flux
            np.copyto(sflx_ig_prev, self._sflxes[g])
            self._sflxes[g] *= 0
            for d in xrange(self._n_dir):
                # if not factorized, factorize the the HO matrices
                cp = self._comp[(g, d)]
                if cp not in self._lu:
                    self._lu[cp] = sla.splu(self._sys_mats[cp])
                # solve direction d
                self._aflxes[cp] = self._lu[cp].solve(self._sys_rhses[cp])
                self._sflxes[g] += self._aq['wt'][d] * self._aflxes[cp]
            # calculate difference for SI convergence
            e = norm(sflx_old_ig - self._sflxes[g], 1) / norm(
                self._sflxes[g], 1)

    #NOTE: this function has to be removed if abstract class is implemented
    def update_sflxes(self, sflxes_old, g):
        '''@brief A function used to update scalar flux for group g

        @param sflxes_old A dictionary
        @param g Group index
        '''
        np.copyto(sflxes_old[g], self._sflxes[g])

    def calculate_keff(self):
        assert not self._is_eigen, 'only be called in eigenvalue problems'
        # update the previous fission source and previous keff
        self._global_fiss_src_prev, self._keff_prev = self._global_fiss_src, self._keff
        # calculate the new fission source
        self._global_fiss_src = self._calculate_fiss_src()
        # calculate the new keff
        self._keff = self._keff_prev * self._global_fiss_src / self._global_fiss_src_prev
        return self._keff

    def _calculate_fiss_src(self):
        # loop over cells and groups and calculate nu_sig_f*phi
        # NOTE: the following calculation is using mid-point rule for integration
        # It will suffice only for constant,RT1 and bilinear finite elements.
        global_fiss_src = 0
        for cell in self._mesh.cells():
            idx, mid = cell.global_idx(), cell.get('id')
            nusigf = self._nu_sigfs[mid]
            for g in filter(lambda x: nusigf[x] > 1.0e-14,
                            xrange(self._n_grp)):
                sflx_vtx = sum(self._sflxes[g][idx])
                global_fiss_src += nusigf[g] * sflx_vtx
        return global_fiss_src

    def calculate_sflx_diff(self, sflxes_old, g):
        '''@brief function used to generate ho scalar flux for Group g using
        angular fluxes

        @param sflx_old Scalar flux from previous generation
        @param g The group index
        @return double The relative difference between new and old scalar flux
        '''
        # return the l1 norm relative difference
        return norm(
            (self._sflxes[g] - sflxes_old[g]), 1) / norm(self._sflxes[g], 1)

    def calculate_nda_cell_correction(self, mat_id, idx, do_ua=False):
        # TODO: address the "9"
        corrs = {
            'x_comp': np.zeros((self._n_grp, 9)),
            'y_comp': np.zeros((self._n_grp, 9))
        }
        for g in xrange(self._n_grp):
            dcoef = self._dcoefs[mat_id][g]
            isgit = self._isigts[mat_id][g]
            # retrive grad_aflx for all directions at quadrature points
            grad_aflxes_qp = {
                d: self._elem.get_grad_at_qps(self._aflxes[self._comp(g,
                                                                      d)][idx])
                for d in self._n_dir
            }
            sflxes_qp = self._elem.get_sol_at_qps(self._sflxes[g][idx])
            grad_sflx_qp = self._elem.get_grad_at_qps(self._sflxes[g][idx])
            # calculate correction for x and y components
            corx, cory = np.zeros(len(sflxes_qp)), np.zeros(len(sflxes_qp))
            for i in len(sflxes_qp):
                # transport current
                tc = np.zeros(2)
                for d in xrange(self._n_dir):
                    # NOTE: 'wt_tensor' is equal to w*OmegaOmega, a 2x2 matrix
                    tc += np.dot(self._aq['wt_tensor'][d],
                                 grad_aflxes_qp[d][i])
                # minus diffusion current
                mdc = dcoef * grad_sflx_qp
                # corrections
                corx[i], cory[i] = (isgit * tc + mdc) / sflxes_qp[i]
            # wrap corrections to corrs
            corrs['x_comp'][g], corrs['y_comp'][g] = corx, cory
        # do upscattering acceleration
        if do_ua:
            corrs['x_ua'] = np.dot(self._ksi_ua[mat_id],
                                   corrs['x_comp'][self._g_thr:, ])
            corrs['y_ua'] = np.dot(self._ksi_ua[mat_id],
                                   corrs['y_comp'][self._g_thr:, ])
        return corrs

    def get_sflxes(self, g):
        '''@brief Function called outside to retrieve the scalar flux value for Group g

        @param g Target group number
        '''
        return self._sflxes[g]

    def get_keff(self):
        '''@brief A function used to retrieve keff

        @return keff calculated in SAAF class
        '''
        return self._keff

    def n_dof(self):
        return self._mesh.n_node()

    def n_grp(self):
        return self._n_grp
Ejemplo n.º 13
0
 def __init__(self, mat_cls, mesh_cls, prob_dict):
     # name of the Equation
     self._name = 'saaf'
     # mesh data
     self._mesh = mesh_cls
     self._cell_length = mesh_cls.cell_length()
     # quantities of interest
     self._keff = 1.0
     self._keff_prev = 1.0
     # preassembly-interpolation data
     self._elem = Elem(self._cell_length)
     # material data
     self._n_grp = mat_cls.get('n_grps')
     self._g_thr = mat_cls.get('g_thermal')
     self._sigts = mat_cls.get('sig_t')
     self._isigts = mat_cls.get('inv_sig_t')
     self._fiss_xsecs = mat_cls.get_per_str('chi_nu_sig_f')
     self._nu_sigfs = mat_cls.get('nu_sig_f')
     self._sigses = mat_cls.get_per_str('sig_s')
     self._dcoefs = mat_cls.get('diff_coef')
     self._mids = mat_cls.ids()
     # derived material data
     self._ksi_ua = mat_cls.get('ksi_ua')
     # problem type: is problem eigenvalue problem
     # aq data in forms of dictionary
     self._aq = AQ(prob_dict['sn_order']).get_aq_data()
     self._n_dir = self._aq['n_dir']
     # total number of components in HO
     self._n_tot = self._n_grp * self._n_dir
     # get a component indexing mapping
     self._comp = dict()
     # component to group map
     self._comp_grp = dict()
     # component to direction map
     self._comp_dir = dict()
     self._generate_component_map()
     # local vectors
     self._rhs_mats = dict()
     self._preassembly_rhs()
     # related to global matrices and vectors
     self._n_dof = mesh_cls.n_node()
     self._sys_mats = {}
     # be very careful about the following
     self._sys_rhses = {
         k: np.ones(self._n_dof)
         for k in xrange(self._n_tot)
     }
     self._fixed_rhses = {
         k: np.zeros(self._n_dof)
         for k in xrange(self._n_tot)
     }
     self._aflxes = {k: np.ones(self._n_dof) for k in xrange(self._n_tot)}
     # scalar flux for current calculation
     self._sflxes = {k: np.ones(self._n_dof) for k in xrange(self._n_grp)}
     # linear solver objects
     self._lu = {}
     # source iteration tol
     self._tol = 1.0e-7
     # fission source
     self._global_fiss_src = self._calculate_fiss_src()
     self._global_fiss_src_prev = self._global_fiss_src
     # assistance:
     self._local_dof_pairs = pd(xrange(4), xrange(4))
Ejemplo n.º 14
0
 def __init__(self, content=None, attr={}):
     Elem.__init__(self,
                   tag="meta",
                   attr=attr,
                   content=content,
                   tag_type='one')