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