Exemplo n.º 1
0
    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 cgen.Module(result)

        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.append(cgen.Statement('printf("%d\\n")' % self.spacing[i].value))

        for field in self.fields:
            body = []
            l2 = ccode(field.label)+'_l2'
            idx = [ti] + loop
            result.append(cgen.Initializer(cgen.Value(self.real_t, l2), 0.0))
            # populate xvalue, yvalue zvalue code
            for d in range(self.dimension-1, -1, -1):
                i = loop[d]
                i0 = m
                i1 = ccode(self.dim[d]-m)
                expr = self.spacing[d]*(loop[d] - self.margin.value)
                pre = [cgen.Initializer(cgen.Value(self.real_t, self.index[d].name), ccode(expr))]

                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 = [cgen.Statement('%s += %s' % (l2, ccode((field[idx] - (field.sol.subs(self.t, tn)))**2.0)))]
                body = pre+body
                body = [cgen.For(cgen.InlineInitializer(cgen.Value('int', i), i0), cgen.Line('%s<%s' % (i, i1)), cgen.Line('++%s' % i), cgen.Block(body))]

            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.append(cgen.Statement('conv->%s = %s' % (l2, l2_value)))

        return cgen.Module(result)
Exemplo n.º 2
0
 def save_field_block(self, filename, field):
     statements = []
     statements.append(cgen.Initializer(cgen.Value("int", "dims[]"), "{dim1, dim1, dim1}"))
     statements.append(cgen.Initializer(cgen.Value("float", "spacing[]"), "{dx1, dx2, dx3}"))
     statements.append(cgen.Assign("std::string vtkfile", "\""+filename+"\" + std::to_string(_ti)"))
     statements.append(cgen.Statement("opesci_dump_field_vts_3d(vtkfile, dims, spacing, 2, &"+field+"["+ccode(self.time[len(self.time)-1])+"][0][0][0])"))
     return cgen.Module([cgen.Pragma("omp single"), cgen.Block(statements)])
Exemplo n.º 3
0
    def initialise(self):
        loop = [Symbol('_'+x.name) for x in self.index]  # symbols for loop

        statements = []
        
        for field in self.fields:
            body = []
            if self.omp:
                statements.append(cgen.Pragma('omp for schedule(static,1)'))
            # populate xvalue, yvalue zvalue code
            for d in range(self.dimension-1, -1, -1):
                i = loop[d]
                i0 = 0
                i1 = ccode(self.dim[d])
                pre = []
                #velocity_initialisation = cgen.Assign(ccode())
                post = []
                if d == self.dimension-1:
                    # inner loop
                    # first time step
                    t0 = 0
                    sol = field.sol.subs(self.t, t0)
                    for idx in self.index:
                        sol = sol.subs(idx, '_'+idx.name)
                    body = [cgen.Assign(ccode(field[[0]+loop]), ccode(sol))]
                body = pre + body + post
                body = [cgen.For(cgen.InlineInitializer(cgen.Value('int', i), i0), cgen.Line('%s<%s' % (i, i1)), cgen.Line('++%s' % i), cgen.Block(body))]

            statements.append(body[0])
            statements += self.generate_second_initialisation()
            
            
        return cgen.Module(statements)
Exemplo n.º 4
0
    def generate_loop(self, fields):
        """
        The functions to generate stress loops and velocity loops are identical,
        save for a single parameter. Moved the common code to this function to reduce repetition of code.
        """
        if self.eval_const:
            self.create_const_dict()
        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
                if not self.fission:
                    body = self.simple_kernel(fields, [d, i, i0, i1])
                else:
                    body = self.fission_kernel(fields, [d, i, i0, i1])
            if not d == self.dimension-1:
                body = [cgen.For(cgen.InlineInitializer(cgen.Value('int', i), i0), cgen.Line('%s<%s' % (i, i1)), cgen.Line('++%s' % i), cgen.Block(body))]

        if not self.pluto and self.omp:
            body.insert(0, cgen.Pragma('omp for schedule(static,1)'))
        return cgen.Module(body)
Exemplo n.º 5
0
    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
        """

        _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.append(cgen.Assign(lhs, rhs))

        body = cgen.Block(body)
        body = cgen.Module([cgen.Pragma('omp single'), body])
        return body
Exemplo n.º 6
0
    def declare_fields(self):
        """
        - generate code for declaring fields
        - the generated code first declare fields as std::vector
        of size=vec_size, then cast to multidimensional array
        - return the generated code as string
        """
        result = []
        arr = ''  # = [dim1][dim2][dim3]...
        for d in self.dim:
            arr += '[' + d.name + ']'
        vsize = 1
        for d in self.dim:
            vsize *= d.value

        vsize *= len(self.time)
        statements = []
        for field in self.fields:
            vec = "_%s_vec" % ccode(field.label)
            vec_value = cgen.Pointer(cgen.Value(self.real_t, vec))
            # alloc aligned memory (on windows and linux)
            statements.append(vec_value)
            ifdef = cgen.IfDef('_MSC_VER', [cgen.Assign(vec, '(%s*) _aligned_malloc(%s*sizeof(%s), %s)' % (self.real_t, str(vsize), self.real_t, str(self.alignment)))],
                               [cgen.Statement('posix_memalign((void **)(&%s), %d, %d*sizeof(%s))' % (vec, self.alignment, vsize, self.real_t))])
            statements.append(ifdef)
            # cast pointer to multidimensional array
            cast_pointer = cgen.Initializer(cgen.Value(self.real_t, "(*%s)%s" % (ccode(field.label), arr)), '(%s (*)%s) %s' % (self.real_t, arr, vec))
            statements.append(cast_pointer)
        vec = "_%s_vec" % ccode("m")
        vec_value = cgen.Pointer(cgen.Value(self.real_t, vec))
        statements.append(vec_value)
        result += statements
        return cgen.Module(result)
Exemplo n.º 7
0
    def store_fields(self):
        """Code fragment that stores field arrays to 'grid' struct"""
        result = []
        for f in self.fields:
            assignment = cgen.Assign('grid->%s' % ccode(f.label), '(%s*) %s' % (self.real_t, ccode(f.label)))  # There must be a better way of doing this. This hardly seems better than string manipulation
            result.append(assignment)

        return cgen.Module(result)
Exemplo n.º 8
0
    def define_fields(self):
        """Code fragment that defines field arrays"""
        result = []
        for f in self.fields:
            var = cgen.Pointer(cgen.Value(self.real_t, ccode(f.label)))
            result.append(var)

        return cgen.Module(result)
Exemplo n.º 9
0
 def define_papi_events(self):
     """Code fragment that starts PAPI counters for specified events"""
     code = []
     code.append(cgen.Initializer(cgen.Value('int', 'numevents'), self.numevents_papi))
     code.append(cgen.ArrayOf(cgen.Value('int', 'events'), self.numevents_papi))
     code.append(cgen.ArrayOf(cgen.Value('long long', 'counters'), self.numevents_papi))
     code += [cgen.Statement('opesci_papi_name2event("%s", &(events[%d]))' % (e, i)) for i, e in enumerate(self._papi_events)]
     return cgen.Module(code)
Exemplo n.º 10
0
    def load_fields(self):
        """Code fragment that loads field arrays from 'grid' struct"""
        idxs = ''.join(['[%d]' % d.value for d in self.dim])
        result = []
        for f in self.fields:
            back_assign = cgen.Initializer(cgen.Value(self.real_t, "(*%s)%s" % (ccode(f.label), idxs)), '(%s (*)%s) grid->%s' % (self.real_t, idxs, ccode(f.label)))  # Another hackish attempt.
            result.append(back_assign)

        return cgen.Module(result)
Exemplo n.º 11
0
    def free_memory(self):
        """
       - generate code for free allocated memory
       - return the generated code as string
       """
        statements = []
        for field in self.fields:
            # alloc aligned memory (on windows and linux)
            ifdef = cgen.IfDef('_MSC_VER', [cgen.Statement('_aligned_free(grid->%s)' % (ccode(field.label)))],
                               [cgen.Statement('free(grid->%s)' % (ccode(field.label)))])
            statements.append(ifdef)

        return cgen.Module(statements)
Exemplo n.º 12
0
    def define_constants(self):
        """
        - generate code for declaring variables
        - return the generated code as string
        """

        result = []
        variables = self.get_all_variables()
        for v in variables:
            if v.constant:
                line = cgen.Initializer(cgen.Const(cgen.Value(v.type, v.name)), v.value)
            else:
                line = cgen.Initializer(cgen.Value(v.type, v.name), v.value)
            result.append(line)

        return cgen.Module(result)
Exemplo n.º 13
0
 def print_convergence(self):
     """Code fragment that prints convergence norms"""
     statements = [cgen.Statement('printf("%s %s\\n", conv.%s_l2)' % (ccode(f.label), '\t%.10f', ccode(f.label))) for f in self.fields]
     return cgen.Module(statements)
Exemplo n.º 14
0
 def define_convergence(self):
     """Code fragment that defines convergence norms"""
     result = []
     for f in self.fields:
         result.append(cgen.Value(self.real_t, '%s_l2' % ccode(f.label)))
     return cgen.Module(result)
Exemplo n.º 15
0
 def define_profiling(self):
     """Code fragment that defines global PAPI counters and events"""
     code = [cgen.Value('float', 'g_%s' % v) for v in ['rtime', 'ptime', 'mflops']]
     code += [cgen.Value('long long', 'g_%s' % e) for e in self._papi_events]
     return cgen.Module(code)
Exemplo n.º 16
0
 def sum_papi_events(self):
     """Code fragment that reads PAPI counters for specified events"""
     code = [cgen.Statement('profiling->g_%s += counters[%d]' % (e, i)) for i, e in enumerate(self._papi_events)]
     return cgen.Module(code)
Exemplo n.º 17
0
 def init_profiling(self):
     """Code fragment that initialises global PAPI counters and events"""
     code = [cgen.Assign('profiling->g_%s' % v, 0.0) for v in ['rtime', 'ptime', 'mflops']]
     code += [cgen.Assign('profiling->g_%s' % e, 0) for e in self._papi_events]
     return cgen.Module(code)