示例#1
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)
示例#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)])
示例#3
0
    def generate_second_initialisation(self):
        loop = [Symbol('_'+x.name) for x in self.index]  # symbols for loop
        m = self.margin.value
        statements = []
        v = symbols("v")
        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 = m
                i1 = ccode(self.dim[d]-m)
                pre = []

                post = []
                if d == self.dimension-1:
                    # inner loop
                    # first time step
                    kernel = self.transform_kernel(field)
                    for arg in kernel.args:
                        if str(arg).startswith("-") and str(self.t - 1) in str(arg):
                            kernel = kernel.subs({arg: 0}, simultaneous=True)
                            arg = 2*v*self.dt
                            kernel = 0.5*(kernel + arg)
                    kernel = kernel.subs({self.t: self.time[0]})
                    for idx in self.index:
                        kernel = kernel.subs(idx, '_'+idx.name)
                    body = [cgen.Assign(ccode(field[[self.time[1]]+loop]), ccode(kernel))]
                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])
        return statements
示例#4
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)
示例#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
示例#6
0
 def simple_kernel(self, grid_field, indexes):
     """
     Generate the inner loop with all fields from stress or velocity
     :param grid_field: stress or velocity field array
     :param indexes: array with dimension, dimension var, initial margin, final margin
     - iterate through fields and replace mako template
     - return inner loop code as string
     """
     body = []
     idx = [self.time[len(self.time)-1]] + self.index
     # This loop create the most inner loop with all fields
     for field in grid_field:
         body.append(cgen.Assign(ccode(field[idx]), ccode(self.kernel_sympy(field))))
     body = [cgen.For(cgen.InlineInitializer(cgen.Value('int', indexes[1]), indexes[2]), cgen.Line('%s<%s' % (indexes[1], indexes[3])), cgen.Line('++%s' % indexes[1]), cgen.Block(body))]
     if not self.pluto and self.ivdep and indexes[0] == self.dimension-1:
         body.insert(0, self.compiler._ivdep)
     if not self.pluto and self.simd and indexes[0] == self.dimension-1:
         body.insert(0, cgen.Pragma('simd'))
     return body
示例#7
0
 def _ivdep(self):
     return cgen.Pragma('ivdep')