def velocity_bc(self):
        """
        generate code for updating stress field boundary ghost cells
        - generate inner loop by inserting boundary code (saved in field.bc)
        - recursive insertion to generate nested loop
        - loop through all velocity fields and sides
        return generated code as string
        """
        tmpl = self.lookup.get_template('generic_loop.txt')
        result = ''
        for d in range(self.dimension):
            # update the staggered field first
            # because other fields depends on it
            sequence = [f for f in self.vfields if f.staggered[d+1]] \
                + [f for f in self.vfields if not f.staggered[d+1]]
            for field in sequence:
                for side in range(2):
                    # skip if this boundary calculation is not needed
                    if field.bc[d+1][side] == '':
                        continue
                    if self.omp:
                        result += '#pragma omp for\n'
                    body = ''
                    for d2 in range(self.dimension-1, -1, -1):
                        # loop through other dimensions
                        if not d2 == d:
                            i = self.index[d2]
                            i0 = 1
                            i1 = self.dim[d2]-1
                            if body == '':
                                # inner loop, populate ghost cell calculation
                                body = field.bc[d+1][side]
                                dict1 = {'i': i, 'i0': i0,
                                         'i1': i1, 'body': body}
                                body = render(tmpl, dict1).replace('[t]',
                                                                   '[t1]')
                                if self.ivdep:
                                    body = '%s\n' % self.compiler._ivdep + body
                                if self.simd:
                                    body = '#pragma simd\n' + body
                            else:
                                dict1 = {'i': i, 'i0': i0,
                                         'i1': i1, 'body': body}
                                body = render(tmpl, dict1).replace('[t]',
                                                                   '[t1]')

                    result += body

        return result
    def time_stepping(self):
        """
        generate time index variable for time stepping
        e.g. for 2nd order time-accurate scheme, varibales are t0, t1
        for 4th order time-accurate scheme, variables are t0, t1, t2, t3
        the variables are used to address the field arrays
        e.g. in 2nd order scheme, U[t1] will be updated using U[t0]
        the variables are calculated by taking mod with time periodicity
        return generated code as string
        """

        result = ''
        tmpl = self.lookup.get_template('time_stepping.txt')
        _ti = Symbol('_ti')
        body = ''

        for i in range(len(self.time)):
            lhs = self.time[i].name
            if i == 0:
                rhs = ccode(_ti % self.tp)
            else:
                rhs = ccode((self.time[i-1]+1) % self.tp)
            body += lhs + ' = ' + rhs + ';\n'

        dict1 = {'body': body}
        result = render(tmpl, dict1)
        return result
    def converge_test(self):
        """
        - generate code for convergence test
        - convergence test implemented by calculating L2 norm
        of the simulation against analytical solution
        - L2 norm of each field is calculated and output with printf()
        - return generated code as string
        """
        result = ''
        if not self.converge:
            return result
        tmpl = self.lookup.get_template('generic_loop.txt')
        m = self.margin.value
        ti = self.ntsteps.value % 2  # last updated grid
        loop = [Symbol('_'+x.name) for x in self.index]  # symbols for loop

        for i in range(len(self.spacing)):
            result += 'printf("' + str(self.spacing[i].value) + '\\n");\n'

        for field in self.sfields+self.vfields:
            body = ''
            l2 = ccode(field.label)+'_l2'
            idx = [ti] + loop
            result += self.real_t + ' ' + l2 + ' = 0.0;\n'
            # populate xvalue, yvalue zvalue code
            for d in range(self.dimension-1, -1, -1):
                i = loop[d]
                i0 = m
                if field.staggered[d+1]:
                    i1 = ccode(self.dim[d]-m-1)
                    expr = self.spacing[d]*(loop[d] - self.margin.value + 0.5)
                else:
                    i1 = ccode(self.dim[d]-m)
                    expr = self.spacing[d]*(loop[d] - self.margin.value)
                pre = self.real_t + ' ' + self.index[d].name + '= ' \
                    + ccode(expr) + ';\n'
                if d == self.dimension-1:
                    # inner loop
                    tn = self.dt.value*self.ntsteps.value \
                        if not field.staggered[0] \
                        else self.dt.value*self.ntsteps.value \
                        + self.dt.value/2.0
                    body = l2 + '+=' \
                        + ccode((field[idx] -
                                (field.sol.subs(self.t, tn)))**2.0) + ';\n'
                body = pre + body
                dict1 = {'i': i, 'i0': i0, 'i1': i1, 'body': body}
                body = render(tmpl, dict1)

            result += body
            volume = 1.0
            for i in range(len(self.spacing)):
                volume *= self.spacing[i].value
            l2_value = 'pow(' + l2 + '*' + ccode(volume) + ', 0.5)'
            result += 'conv->%s = %s;\n' % (l2, l2_value)

        return result
Exemple #4
0
    def vtk_save_field(self):
        """
        generate code to output this field with vtk
        uses Mako template
        returns the generated code as string
        """
        tmpl = self.lookup.get_template('save_field.txt')
        result = ''
        dict1 = {'filename': ccode(self.label)+'_', 'field': ccode(self.label)}
        result = render(tmpl, dict1)

        return result
    def initialise(self):
        """
        generate code for initialisation of the fields
        - substitute starting time to the analytical function of the fields
        - substitute field coordinates calculated from array indices
        to the analytical function of the fields
        - generate inner loop by inserting kernel into Mako template
        - recursive insertion to generate nested loop
        return generated code as string
        """

        tmpl = self.lookup.get_template('generic_loop.txt')
        result = ''
        m = self.margin.value
        loop = [Symbol('_'+x.name) for x in self.index]  # symbols for loop

        for field in self.sfields+self.vfields:
            body = ''
            if self.omp:
                result += '#pragma omp for\n'
            # populate xvalue, yvalue zvalue code
            for d in range(self.dimension-1, -1, -1):
                i = loop[d]
                i0 = m
                if field.staggered[d+1]:
                    i1 = ccode(self.dim[d]-m-1)
                    expr = self.spacing[d]*(loop[d] - self.margin.value + 0.5)
                else:
                    i1 = ccode(self.dim[d]-m)
                    expr = self.spacing[d]*(loop[d] - self.margin.value)
                pre = self.real_t + ' ' + self.index[d].name + '= ' \
                    + ccode(expr) + ';\n'
                post = ''
                if d == self.dimension-1:
                    # inner loop
                    # first time step
                    t0 = self.dt.value/2 if field.staggered[0] else 0
                    sol = field.sol.subs(self.t, t0)
                    if self.read:
                        sol = sol.subs(field.media_param)
                        for idx in self.index:
                            sol = sol.subs(idx, '_'+idx.name)
                    body = ccode(field[[0]+loop]) + '=' \
                        + ccode(sol) + ';\n'
                body = pre + body + post
                dict1 = {'i': i, 'i0': i0, 'i1': i1, 'body': body}
                body = render(tmpl, dict1)

            result += body
        return result
Exemple #6
0
    def vtk_save_field(self):
        """
        generate code to output this field with vtk
        uses Mako template
        returns the generated code as string
        """
        tmpl = self.lookup.get_template('save_field.txt')
        result = ''
        dict1 = {
            'filename': ccode(self.label) + '_',
            'field': ccode(self.label)
        }
        result = render(tmpl, dict1)

        return result
 def simple_loop(self, kernel):
     """
     - helper function to generate simple nested loop over the entire domain
     (not including ghost cells) with kernel at the inner loop
     - variables defined in self.index are used as loop variables
     """
     result = ''
     tmpl = self.lookup.get_template('generic_loop.txt')
     m = self.margin.value
     for d in range(self.dimension-1, -1, -1):
         i = self.index[d]
         i0 = m
         i1 = ccode(self.dim[d]-m)
         if d == self.dimension-1:
             # inner loop
             result += kernel + ';\n'
         dict1 = {'i': i, 'i0': i0, 'i1': i1, 'body': result}
         result = render(tmpl, dict1)
     return result
    def velocity_loop(self):
        """
        generate code for velocity field update loop
        - loop through velocity fields to generate code of computation kernel
        - generate inner loop by inserting kernel into Mako template
        - recursive insertion to generate nested loop
        return generated code as string
        """
        tmpl = self.lookup.get_template('generic_loop.txt')
        m = self.margin.value
        body = ''
        for d in range(self.dimension-1, -1, -1):
            i = self.index[d]
            i0 = m
            i1 = ccode(self.dim[d]-m)
            if d == self.dimension-1:
                # inner loop
                idx = [self.time[1]] + self.index
                for field in self.vfields:
                    body += ccode(field[idx]) + '=' \
                        + ccode(field.fd_align.xreplace({self.t+1:
                                                        self.time[1],
                                                        self.t:
                                                        self.time[0]})) \
                        + ';\n'
            dict1 = {'i': i, 'i0': i0, 'i1': i1, 'body': body}
            body = render(tmpl, dict1)
            if self.ivdep and d == self.dimension-1:
                    body = '%s\n' % self.compiler._ivdep + body
            if self.simd and d == self.dimension-1:
                    body = '#pragma simd\n' + body

        if self.omp:
            body = '#pragma omp for\n' + body

        return body