def adjust_stepsize(self, state, h, order, y, y_err, dydt):
        # [y] = A/m.
        # [dydt] = A/m (deriviative of y).
        # [y_err] = A/m (estimated error dydt).
        # - One RK step: y = y_prev + (h*dydt +- y_err)

        max_y_err = magneto.scaled_abs_max(
            y_err, state.Ms
        )  # max_y_err = max_i(|y_err[i]| / Ms[i]), [max_y_err] = rad
        max_dydt = magneto.scaled_abs_max(
            dydt, state.Ms
        )  # max_dydt  = max_i(|dydt[i]| / Ms[i]),  [max_dydt]  = rad/s

        # Calculate estimated absolute and relative error.
        try:
            e_abs = max_y_err  # [e_abs] = rad
            e_rel = e_abs / (h * max_dydt)  # [e_rel] = 1
        except ZeroDivisionError:
            print("ZeroDivisionError!")
            return True, 5e-14

        # Accept the step only with tolerable errors.
        accept = (e_abs <= self.allowed_absolute_error) and (
            e_rel <= self.allowed_relative_error)

        # Determine step size scaling factor for allowed absolute and relative errors.
        h_scale_abs = self.STEP_HEADROOM * pow(
            self.allowed_absolute_error / e_abs, 1.0 / (order + 1.0))
        h_scale_rel = self.STEP_HEADROOM * pow(
            self.allowed_relative_error / e_rel, 1.0 / order)

        def clamp(x, min_x, max_x):
            if x < min_x: x = min_x
            if x > max_x: x = max_x
            return x

        # Take the most pessimistic (= smallest) scaling factor and clamp by [max_step_decrease, max_step_increase]
        h_scale = clamp(min([h_scale_abs, h_scale_rel]),
                        self.MIN_TIMESTEP_SCALE, self.MAX_TIMESTEP_SCALE)

        # Determine next step size and clamp by [min_h, max_h]
        h_next = clamp(h * h_scale, self.MIN_TIMESTEP, self.MAX_TIMESTEP)

        # Accept step anyway if time step can not go any smaller.
        if h_next == self.MIN_TIMESTEP: accept = True

        return accept, h_next
  def test_1(self):
    mesh = RectangularMesh((10,10,10), (1e-9,1e-9,1e-9))

    M = VectorField(mesh); M.fill((-8e5,0,0))
    Ms = Field(mesh); Ms.fill(8e5)

    sam = magneto.scaled_abs_max(M, Ms)
    self.assertEqual(1.0, sam)
示例#3
0
    def test_1(self):
        mesh = RectangularMesh((10,10,10), (1e-9,1e-9,1e-9))

        M = VectorField(mesh); M.fill((-8e5,0,0))
        Ms = Field(mesh); Ms.fill(8e5)

        sam = magneto.scaled_abs_max(M, Ms)
        self.assertEqual(1.0, sam)
    def test_2(self):
        mesh = RectangularMesh((10, 10, 10), (1e-9, 1e-9, 1e-9))

        M = VectorField(mesh)
        M.fill((-8e5, 0, 0))
        Ms = Field(mesh)
        Ms.fill(8e5)
        Ms.set(0, 0)
        Ms.set(0, 8e5)
        self.assertFalse(Ms.isUniform())

        sam = magneto.scaled_abs_max(M, Ms)
        self.assertEqual(1.0, sam)
    def test_2(self):
        mesh = RectangularMesh((10, 10, 10), (1e-9, 1e-9, 1e-9))

        M = VectorField(mesh)
        M.fill((-8e5, 0, 0))
        Ms = Field(mesh)
        Ms.fill(8e5)
        Ms.set(0, 0)
        Ms.set(0, 8e5)
        self.assertFalse(Ms.isUniform())

        sam = magneto.scaled_abs_max(M, Ms)
        self.assertEqual(1.0, sam)
  def adjust_stepsize(self, state, h, order, y, y_err, dydt):
    # [y] = A/m.
    # [dydt] = A/m (deriviative of y).
    # [y_err] = A/m (estimated error dydt).
    # - One RK step: y = y_prev + (h*dydt +- y_err)

    max_y_err = magneto.scaled_abs_max(y_err, state.Ms) # max_y_err = max_i(|y_err[i]| / Ms[i]), [max_y_err] = rad
    max_dydt  = magneto.scaled_abs_max(dydt, state.Ms)  # max_dydt  = max_i(|dydt[i]| / Ms[i]),  [max_dydt]  = rad/s

    # Calculate estimated absolute and relative error.
    try:
      e_abs = max_y_err            # [e_abs] = rad
      e_rel = e_abs / (h*max_dydt) # [e_rel] = 1
    except ZeroDivisionError:
      print("ZeroDivisionError!")
      return True, 5e-14

    # Accept the step only with tolerable errors.
    accept = (e_abs <= self.allowed_absolute_error) and (e_rel <= self.allowed_relative_error)

    # Determine step size scaling factor for allowed absolute and relative errors.
    h_scale_abs = self.STEP_HEADROOM * pow(self.allowed_absolute_error / e_abs, 1.0/(order+1.0))
    h_scale_rel = self.STEP_HEADROOM * pow(self.allowed_relative_error / e_rel, 1.0/order)

    def clamp(x, min_x, max_x):
      if x < min_x: x = min_x
      if x > max_x: x = max_x
      return x
    
    # Take the most pessimistic (= smallest) scaling factor and clamp by [max_step_decrease, max_step_increase]
    h_scale = clamp(min([h_scale_abs, h_scale_rel]), self.MIN_TIMESTEP_SCALE, self.MAX_TIMESTEP_SCALE)
    
    # Determine next step size and clamp by [min_h, max_h]
    h_next = clamp(h * h_scale, self.MIN_TIMESTEP, self.MAX_TIMESTEP)

    # Accept step anyway if time step can not go any smaller.
    if h_next == self.MIN_TIMESTEP: accept = True

    return accept, h_next