Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions examples/magnetoelastic.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,6 @@ def displacement_to_scatter_data(magnet, scale, skip):
u_scale = 5e4 # amplification of displacement
u_skip = 5 # don't show every displacement

world.timesolver.adaptive_timestep = False
world.timesolver.timestep = 1e-12

steps = 400
time_max = 0.8e-9
duration = time_max/steps
Expand Down
4 changes: 0 additions & 4 deletions examples/magnetoelastic_dispersion.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,6 @@ def simulation(theta):
magnet.alpha = 0
magnet.eta = 0

# time stepping
world.timesolver.adaptive_timestep = False
world.timesolver.timestep = 1e-13
Comment on lines -85 to -86

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think dispersion relations generally show up better with fixed timestepping 🤔


# parameters to save
m = np.zeros(shape=(nt, 3, nz, ny, nx))
u = np.zeros(shape=(nt, 3, nz, ny, nx))
Expand Down
4 changes: 0 additions & 4 deletions examples/pure_elastic.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,6 @@ def displacement_to_scatter_data(magnet, scale, skip):
u[i, ...] -= u_avg[i]
magnet.elastic_displacement = u

# adaptive time stepping does not work for magnetoelastics
world.timesolver.adaptive_timestep = False
world.timesolver.timestep = 1e-13

# simulation
time = np.linspace(0, 1e-10, 500)
energies = {"E_kin": lambda : magnet.kinetic_energy.eval()*J_to_eV,
Expand Down
66 changes: 56 additions & 10 deletions mumaxplus/timesolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,23 +159,65 @@ def time(self, time):
self._impl.time = time

@property
def max_error(self):
"""Return the maximum error per step the solver can tollerate.
def magnetization_max_error(self):
"""Return the maximum error per step the solver can tollerate for the
Comment thread
ilateur marked this conversation as resolved.
Outdated
magnetization-torque equations of motion (rad).

The default value is 1e-5.

See Also
--------
headroom, lower_bound, sensible_factor, upper_bound
displacement_max_error, velocity_max_error
"""

return self._impl.max_error
return self._impl.torque_max_error

@max_error.setter
def max_error(self, error):
@magnetization_max_error.setter
def magnetization_max_error(self, error):
assert error > 0, "The maximum error should be bigger than 0."
self._impl.max_error = error
self._impl.magnetization_max_error = error

@property
def displacement_max_error(self):
"""Return the maximum error per step the solver can tollerate for the
displacement-velocity equations of motion (m).

The default value is 1e-18.

See Also
--------
headroom, lower_bound, sensible_factor, upper_bound
Comment thread
ilateur marked this conversation as resolved.
Outdated

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sensible_factor is specifically designed for torque I think, so it does not make much sense here

magnetization_max_error, velocity_max_error
"""

return self._impl.displacement_max_error

@displacement_max_error.setter
def displacement_max_error(self, error):
assert error > 0, "The maximum error should be bigger than 0."
self._impl.displacement_max_error = error

@property
def velocity_max_error(self):
"""Return the maximum error per step the solver can tollerate for the
velocity-acceleration equations of motion (m/s).

The default value is 1e-7.

See Also
--------
headroom, lower_bound, sensible_factor, upper_bound
displacement_max_error, magnetization_max_error

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comments as with displacement_max_error

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(sensible_factor comment remaining)

"""

return self._impl.velocity_max_error

@velocity_max_error.setter
def velocity_max_error(self, error):
assert error > 0, "The maximum error should be bigger than 0."
self._impl.velocity_max_error = error

@property
def headroom(self):
"""Return the solver headroom.
Expand All @@ -184,7 +226,8 @@ def headroom(self):

See Also
--------
lower_bound, max_error, sensible_factor, upper_bound
lower_bound, sensible_factor, upper_bound
displacement_max_error, magnetization_max_error, velocity_max_error
"""
return self._impl.headroom

Expand All @@ -202,7 +245,8 @@ def lower_bound(self):

See Also
--------
headroom, max_error, sensible_factor, upper_bound
headroom, sensible_factor, upper_bound
displacement_max_error, magnetization_max_error, velocity_max_error
"""
return self._impl.lower_bound

Expand All @@ -220,7 +264,8 @@ def upper_bound(self):

See Also
--------
headroom, lower_bound, max_error, sensible_factor
headroom, lower_bound, sensible_factor
displacement_max_error, magnetization_max_error, velocity_max_error
"""
return self._impl.upper_bound

Expand All @@ -238,7 +283,8 @@ def sensible_factor(self):

See Also
--------
headroom, lower_bound, max_error, upper_bound
headroom, lower_bound, upper_bound
displacement_max_error, magnetization_max_error, velocity_max_error
"""
return self._impl.sensible_factor

Expand Down
7 changes: 6 additions & 1 deletion src/bindings/wrap_timesolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,12 @@ void wrap_timesolver(py::module& m) {
})
.def_property("headroom", &TimeSolver::headroom, &TimeSolver::setHeadroom)
.def_property("lower_bound", &TimeSolver::lowerBound, &TimeSolver::setLowerBound)
.def_property("max_error", &TimeSolver::maxError, &TimeSolver::setMaxError)
.def_property("magnetization_max_error", &TimeSolver::magnetizationMaxError,
&TimeSolver::setMagnetizationMaxError)
.def_property("displacement_max_error", &TimeSolver::displacementMaxError,
&TimeSolver::setDisplacementMaxError)
.def_property("velocity_max_error", &TimeSolver::velocityMaxError,
&TimeSolver::setVelocityMaxError)
.def_property("sensible_factor", &TimeSolver::sensibleFactor, &TimeSolver::setSensibleFactor)
.def_property("upper_bound", &TimeSolver::upperBound, &TimeSolver::setUpperBound)
.def("step", &TimeSolver::step)
Expand Down
18 changes: 13 additions & 5 deletions src/core/rungekutta.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,20 +57,20 @@ void RungeKuttaStepper::step() {
if (!solver_->hasAdaptiveTimeStep())
break;

// loop over equations and get the largest error
// loop over equations and get the largest scaled error
real error = 0.0;
for (auto& eq : equations)
if (real e = eq.getError(); e > error)
if (real e = eq.getScaledError(); e > error)
error = e;

success = error < solver_->maxError();
success = error < 1.;

// update the timestep
real corrFactor;
if (success) {
corrFactor = std::pow(solver_->maxError() / error, 1. / (butcher_.order2 + 1));
corrFactor = std::pow(1. / error, 1. / (butcher_.order2 + 1));
} else {
corrFactor = std::pow(solver_->maxError() / error, 1. / (butcher_.order1 + 1));
corrFactor = std::pow(1. / error, 1. / (butcher_.order1 + 1));
}
solver_->adaptTimeStep(corrFactor);

Expand Down Expand Up @@ -149,3 +149,11 @@ real RungeKuttaStepper::RungeKuttaStageExecutor::getError() const {

return maxVecNorm(err);
}

real RungeKuttaStepper::RungeKuttaStageExecutor::maxError() const {
return stepper.solver_->getMaxError(x.maxError());
}

real RungeKuttaStepper::RungeKuttaStageExecutor::getScaledError() const {
return getError() / maxError();
}
2 changes: 2 additions & 0 deletions src/core/rungekutta.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ class RungeKuttaStepper::RungeKuttaStageExecutor {
void setFinalX();
void resetX();
real getError() const;
real maxError() const;
real getScaledError() const;

private:
Field x0;
Expand Down
14 changes: 14 additions & 0 deletions src/core/timesolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "reduce.hpp"
#include "rungekutta.hpp"
#include "stepper.hpp"
#include "variable.hpp"

std::unique_ptr<TimeSolver> TimeSolver::Factory::create() {
return std::unique_ptr<TimeSolver>(new TimeSolver());
Expand All @@ -34,6 +35,19 @@ RKmethod TimeSolver::getRungeKuttaMethod() {
return method_;
}

real TimeSolver::getMaxError(MaxError maxError) const {
switch (maxError) {
case MaxError::MAGNETIZATION:
return this->magnetizationMaxError();
case MaxError::DISPLACEMENT:
return this->displacementMaxError();
case MaxError::VELOCITY:
return this->velocityMaxError();
default:
return this->magnetizationMaxError();
}
}

real TimeSolver::sensibleTimeStep() const {
if (eqs_.empty())
return 0.0; // Timestep is irrelevant if there are no equations to solve
Expand Down
15 changes: 12 additions & 3 deletions src/core/timesolver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

class Stepper;
enum class RKmethod;
enum class MaxError;

class TimeSolver {
//------------- CONSTRUCTORS -------------------------------------------------
Expand All @@ -32,7 +33,10 @@ class TimeSolver {
RKmethod getRungeKuttaMethod();
real headroom() const { return headroom_; }
real lowerBound() const { return lowerBound_; }
real maxError() const { return maxError_; }
real magnetizationMaxError() const { return magnetizationMaxError_; }
real displacementMaxError() const { return displacementMaxError_; }
real velocityMaxError() const { return velocityMaxError_; }
real getMaxError(MaxError) const; // get approprate max error, given enum of Variable
real sensibleFactor() const { return sensibleFactor_; }
real time() const { return time_; }
real timestep() const { return timestep_; }
Expand All @@ -46,7 +50,9 @@ class TimeSolver {
void setEquations(std::vector<DynamicEquation> eq);
void setHeadroom(real headroom) { headroom_ = headroom; }
void setLowerBound(real lowerBound) { lowerBound_ = lowerBound; }
void setMaxError(real maxError) { maxError_ = maxError; }
void setMagnetizationMaxError(real maxError) { magnetizationMaxError_ = maxError; }
void setDisplacementMaxError(real maxError) { displacementMaxError_ = maxError; }
void setVelocityMaxError(real maxError) { velocityMaxError_ = maxError; }
void setSensibleFactor(real factor) { sensibleFactor_ = factor; }
void setTime(real time) { time_ = time; }
void setTimeStep(real dt) { timestep_ = dt; }
Expand All @@ -63,6 +69,7 @@ class TimeSolver {

//------------- HELPER FUNCTIONS FOR ADAPTIVE TIMESTEPPING -------------------

// TODO: take a look at sensible timestep
real sensibleTimeStep() const; /** Computes a sensible timestep */
void adaptTimeStep(real corr);

Expand All @@ -71,7 +78,9 @@ class TimeSolver {

real headroom_ = 0.8;
real lowerBound_ = 0.5;
real maxError_ = 1e-5;
real magnetizationMaxError_ = 1e-5;
real displacementMaxError_ = 1e-18; // TODO: may need to change default value
real velocityMaxError_ = 1e-7; // TODO: may need to change default value
real sensibleFactor_ = 0.01;
real time_ = 0.0;
real timestep_ = 0.0;
Expand Down
13 changes: 9 additions & 4 deletions src/core/variable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
#include "system.hpp"

Variable::Variable(std::shared_ptr<const System> system, int ncomp,
std::string name, std::string unit)
: name_(name), unit_(unit) {
std::string name, std::string unit, MaxError maxError)
: name_(name), unit_(unit), maxError_(maxError) {
field_ = new Field(system, ncomp);
}

Expand All @@ -34,6 +34,10 @@ std::string Variable::unit() const {
return unit_;
}

MaxError Variable::maxError() const {
return maxError_;
}

Field Variable::eval() const {
return field_->eval();
}
Expand Down Expand Up @@ -70,8 +74,9 @@ void Variable::set(real3 value) const {
NormalizedVariable::NormalizedVariable(std::shared_ptr<const System> system,
int ncomp,
std::string name,
std::string unit)
: Variable(system, ncomp, name, unit) {}
std::string unit,
MaxError maxError)
: Variable(system, ncomp, name, unit, maxError) {}

void NormalizedVariable::set(const Field& src) const {
// TODO: check if this is possible without the extra copy
Expand Down
14 changes: 12 additions & 2 deletions src/core/variable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,24 @@
class CuField;
class System;

enum class MaxError {
MAGNETIZATION,
DISPLACEMENT,
VELOCITY
};

class Variable : public FieldQuantity {
public:
Variable(std::shared_ptr<const System> system, int ncomp,
std::string name = "", std::string unit = "");
std::string name = "", std::string unit = "",
MaxError maxError = MaxError::MAGNETIZATION);
~Variable();

int ncomp() const;
std::shared_ptr<const System> system() const;
std::string name() const;
std::string unit() const;
MaxError maxError() const;

Field eval() const;

Expand All @@ -39,14 +47,16 @@ class Variable : public FieldQuantity {
private:
std::string name_;
std::string unit_;
MaxError maxError_; // enum to select appropriate max error for adaptive time stepping
};

// Exactly the same as variable, but when values are set, the values are
// normalized
class NormalizedVariable : public Variable {
public:
NormalizedVariable(std::shared_ptr<const System> system, int ncomp,
std::string name = "", std::string unit = "");
std::string name = "", std::string unit = "",
MaxError maxError = MaxError::MAGNETIZATION);
void set(const Field&) const;
void set(real) const;
void set(real3) const;
Expand Down
2 changes: 1 addition & 1 deletion src/physics/ferromagnet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Ferromagnet::Ferromagnet(std::shared_ptr<System> system_ptr,
Antiferromagnet* hostMagnet)
: Magnet(system_ptr, name),
hostMagnet_(hostMagnet),
magnetization_(system(), 3, name + ":magnetization", ""),
magnetization_(system(), 3, name + ":magnetization", "", MaxError::MAGNETIZATION),
msat(system(), 1.0, name + ":msat", "A/m"),
aex(system(), 0.0, name + ":aex", "J/m"),
interExch(system(), 0.0, name + ":inter_exchange", "J/m"),
Expand Down
6 changes: 4 additions & 2 deletions src/physics/magnet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,10 +187,12 @@ void Magnet::setEnableElastodynamics(bool value) {
if (value) {
// properly initialize Variables now
elasticDisplacement_ = std::make_unique<Variable>(system(), 3,
name() + ":elastic_displacement", "m");
name() + ":elastic_displacement", "m",
MaxError::DISPLACEMENT);
elasticDisplacement_->set(real3{0,0,0});
elasticVelocity_ = std::make_unique<Variable>(system(), 3,
name() + ":elastic_velocity", "m/s");
name() + ":elastic_velocity", "m/s",
MaxError::VELOCITY);
elasticVelocity_->set(real3{0,0,0});
} else {
// free memory of unnecessary Variables
Expand Down
Loading