コード例 #1
0
    def _build_timesteppers(self):
        nlam_tss = {}
        simplify_context = \
          EqSimplifyContext(quantities=self.quantities,
                            material=self.regions.all_entity_names)
        for ts in self.timesteppers._all:
            nr_primary_fields = len(ts.x)
            assert nr_primary_fields == len(ts.dxdt)

            inputs, outputs = \
              ts.eq_for_jacobian.get_inputs_and_outputs(context=simplify_context)

            all_names = inputs + outputs
            x_and_dxdt = ts.x + ts.dxdt
            if contains_all(outputs, ts.dxdt):
                other_names = [name
                               for name in all_names
                               if name not in x_and_dxdt]

            else:
                print ts.dxdt, outputs
                eq = ts.eq_for_jacobian
                msg = ("Jacobian for timestepper %s (x=%s and dxdt=%s) does "
                       "not determine the value of dxdt. The Jacobian is "
                       "%s, which was simplified from: %s."
                       % (ts.name, ts.x, ts.dxdt,
                          eq.simplified_tree, eq.text))
                raise ValueError(msg)

            # List of all quantities involved in jacobi equation
            all_names = x_and_dxdt + other_names

            # Build a dictionary containing info about how to derive each
            # quantity
            how_to_derive = {}
            if ts.derivatives != None:
                for quant, way in ts.derivatives:
                    if isinstance(way, Operator):
                        op_full_name = way.get_full_name()
                        how_to_derive[quant.name] = ("OPERATOR", op_full_name)
                    else:
                        raise ValueError("Timestepper was build specifying "
                          "that %s should be used to compute the derivative "
                          "of %s, but only operators can be used at the "
                          "moment." % (quant.name, way.name))

            all_v_names = ["v_%s" % name for name in all_names]
            derivs = [("PRIMARY", "")]*(2*nr_primary_fields)
            for name in other_names:
                if name in how_to_derive:
                    derivs.append(how_to_derive[name])
                else:
                    derivs.append(("IGNORE", ""))

            # Build dxdt update program
            primaries = {}
            targets_to_make = []
            for dxdt in ts.dxdt:
                self._build_target_maker(dxdt, primaries, targets_to_make)
            if False:
                print "In order to update the RHS I have to:"
                for p in primaries:
                    print "distribute quantity %s" % p
                for t in targets_to_make:
                    print "run computation %s" % t.name
                raw_input()

            dxdt_updater = LAMProgram("TsUp_%s" % ts.name)
            for t in targets_to_make:
                dxdt_updater.add_commands(["GOSUB", t.get_prog_name()])

            self.computations.add(dxdt_updater)
            assert not self._was_built("LAMPrograms"), \
              "Timesteppers should be built before LAM programs!"

            full_name = ts.get_full_name()
            nlam_ts = \
              nlam.lam_timestepper(full_name,
                                   all_names,
                                   all_v_names,
                                   dxdt_updater.get_full_name(),
                                   nr_primary_fields=nr_primary_fields,
                                   name_jacobian=None,
                                   pc_rtol=ts.pc_rtol,
                                   pc_atol=ts.pc_atol,
                                   max_order=ts.max_order,
                                   krylov_max=ts.krylov_max,
                                   jacobi_eom=ts.eq_for_jacobian.get_text(),
                                   phys_field_derivs=derivs,
                                   jacobi_prealloc_diagonal=
                                     ts.jacobi_prealloc_diagonal,
                                   jacobi_prealloc_off_diagonal=
                                     ts.jacobi_prealloc_off_diagonal)

            nlam_tss[full_name] = nlam_ts
        self._built["TSs"] = True
        return nlam_tss