Skip to content

Commit

Permalink
Merge pull request #130 from GollyGang/accuracy
Browse files Browse the repository at this point in the history
Option to change the stencil accuracy
  • Loading branch information
timhutton authored Jan 22, 2021
2 parents 5a0344a + 1bfcde3 commit c3ebc36
Show file tree
Hide file tree
Showing 12 changed files with 210 additions and 46 deletions.
2 changes: 2 additions & 0 deletions Help/changes.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ <h3>Changes</h3>
<li>Formulas now support <b>a_e</b>, <b>a_nw</b> etc. in a more natural way. Instead of accessing the float4 block that is
the neighbor of the current block, these keywords return a float4 that has the four values that are neighbors in the specified way. Now we can do e.g. <tt>a = a_ne;</tt> in a formula to have the whole pattern shift down and left by one pixel. This is a
<b>breaking change</b>: formula rules that accessed cells using a_w, a_e, a_nw, a_se, etc. will no longer behave as they did before.
<li>New pattern setting: <tt>accuracy</tt>. Controls the size of the stencil. Use "low" to run fast, and "high" to run
accurately.
<li>Parameter <b>dx</b> is now reserved for controlling the grid spacing of the Gaussian, Laplacian, bi-Laplacian and tri-Laplacian
stencils. Formula rules no longer need to write e.g. laplacian_a / (delta_x * delta_x) and can just write laplacian_a since the value of dx is used in the stencil computation.
<li>New <a href="formats.html#render_settings">render setting</a>: <b>colormap</b>, with 11 maps available: "HSV blend", "spectral", "spectral reversed", "inferno", "inferno reversed", "terrain", "terrain reversed", "orange-purple", "purple-orange", "brown-teal", "teal-brown". The old behavior (HSV interpolation between two colors) is still available - choose "HSV blend".
Expand Down
1 change: 1 addition & 0 deletions Help/formats.html
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ <h4><a name="formula"></a><b>&lt;formula&gt;</b></h4>
<li><tt>block_size_x</tt> (optional) : The x component of the dimensions of the spatial unit processed by each kernel call. Default: 4x1x1
<li><tt>block_size_y</tt> (optional) : The y component.
<li><tt>block_size_z</tt> (optional) : The z component.
<li><tt>accuracy</tt> (optional) : The stencil accuracy to use. "low", "medium" or "high". Default: "medium".
</ul>
<p>Contains:
<p>An OpenCL kernel snippet, where the chemicals are named a, b, c, etc.
Expand Down
2 changes: 2 additions & 0 deletions Help/quickstart.html
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ <h3>Quick Start</h3>
<li>Select the fastest OpenCL device - use Action > Select OpenCL Device...
<li>Avoid using the same graphics card for rendering, if possible. For example on my laptop I can tell Windows that Ready
should use the integrated graphics chip for rendering (Graphics Settings), which leaves the NVidia card free to run OpenCL.
<li>Change the accuracy to low in the Info Pane, if this does not introduce artifacts into the pattern. View the kernel
to see the effect of this setting.
<li>Set the data type to float if possible. Using double is typically slower.
<li>Try using local memory, with the setting in the Info Pane. This is a recent feature, let us know if it makes a
dramatic difference.
Expand Down
4 changes: 3 additions & 1 deletion Patterns/advection.vti
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
The rate of change is the negative x gradient. The result is that patterns move to the right without changing shape, as
if carried by some bulk flow or &lt;i&gt;advection&lt;/i&gt;.

(After a while distortions and instabilities appear because we are using only simple numerical methods.)
After a while distortions and instabilities appear because we are using only simple numerical methods. To reduce
the distortions, set the accuracy to 'high' below to use a 5-point stencil. To delay the onset of numerical instability,
use a smaller timestep or change the data type to 'double'.
</description>

<rule name="advection" type="formula" neighborhood_type="vertex">
Expand Down
30 changes: 30 additions & 0 deletions src/gui/InfoPanel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ const wxString InfoPanel::data_type_label = _("Data type");
const wxString InfoPanel::neighborhood_type_label = _("Neighborhood");
const wxString InfoPanel::neighborhood_range_label = _("Neighborhood range");
const wxString InfoPanel::neighborhood_weight_label = _("Neighborhood weight");
const wxString InfoPanel::accuracy_label = _("Accuracy");
const wxString InfoPanel::accuracy_labels[3] = { _("low"), _("medium"), _("high") };

// -----------------------------------------------------------------------------

Expand Down Expand Up @@ -188,6 +190,11 @@ void InfoPanel::Update(const AbstractRD& system)
contents += AppendRow(neighborhood_type_label, neighborhood_type_label, system.GetNeighborhoodType() + "-neighbors", false);
}

if (system.HasEditableAccuracyOption())
{
contents += AppendRow(accuracy_label, accuracy_label, accuracy_labels[static_cast<int>(system.GetAccuracy())], true);
}

contents += AppendRow(block_size_label, block_size_label, wxString::Format(wxT("%d x %d x %d"),
system.GetBlockSizeX(),system.GetBlockSizeY(),system.GetBlockSizeZ()),
system.HasEditableBlockSize());
Expand Down Expand Up @@ -602,6 +609,26 @@ void InfoPanel::ChangeDimensions()

// -----------------------------------------------------------------------------

void InfoPanel::ChangeAccuracy()
{
const AbstractRD::Accuracy old_val = frame->GetCurrentRDSystem().GetAccuracy();

wxArrayString choices;
for (const wxString& label : accuracy_labels)
{
choices.Add(label);
}
wxSingleChoiceDialog dlg(this, _("Accuracy:"), _("Select accuracy:"),
choices);
dlg.SetSelection(static_cast<int>(old_val));
if (dlg.ShowModal() != wxID_OK) return;
const AbstractRD::Accuracy new_val = static_cast<AbstractRD::Accuracy>(dlg.GetSelection());
frame->GetCurrentRDSystem().SetAccuracy(new_val);
Update(frame->GetCurrentRDSystem());
}

// -----------------------------------------------------------------------------

void InfoPanel::ChangeBlockSize()
{
const AbstractRD& sys = frame->GetCurrentRDSystem();
Expand Down Expand Up @@ -692,6 +719,9 @@ void InfoPanel::ChangeInfo(const wxString& label)
} else if ( label == dimensions_label ) {
ChangeDimensions();

} else if ( label == accuracy_label ) {
ChangeAccuracy();

} else if ( label == block_size_label ) {
ChangeBlockSize();

Expand Down
3 changes: 3 additions & 0 deletions src/gui/InfoPanel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ class InfoPanel : public wxPanel
static const wxString neighborhood_type_label;
static const wxString neighborhood_range_label;
static const wxString neighborhood_weight_label;
static const wxString accuracy_label;
static const wxString accuracy_labels[3];

private:

Expand All @@ -107,6 +109,7 @@ class InfoPanel : public wxPanel
void ChangeFormula();
void ChangeDimensions();
void ChangeBlockSize();
void ChangeAccuracy();
void ChangeUseLocalMemory();
void ChangeWrapOption();
void ChangeDataType();
Expand Down
2 changes: 1 addition & 1 deletion src/readybase/AbstractRD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ using namespace std;
AbstractRD::AbstractRD(int data_type)
: x_spacing_proportion(0.05)
, y_spacing_proportion(0.1)
, accuracy(Accuracy::Medium)
, use_local_memory(false)
, timesteps_taken(0)
, need_reload_formula(true)
Expand Down Expand Up @@ -417,4 +418,3 @@ void AbstractRD::InternalSetDataType(int type)
}

// ---------------------------------------------------------------------

7 changes: 7 additions & 0 deletions src/readybase/AbstractRD.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,11 @@ class AbstractRD
bool GetWrap() const { return this->wrap; }
virtual void SetWrap(bool w) { this->wrap = w; }

virtual bool HasEditableAccuracyOption() const { return false; }
enum class Accuracy { Low, Medium, High };
Accuracy GetAccuracy() const { return this->accuracy; }
virtual void SetAccuracy(Accuracy acc) { this->accuracy = acc; }

/// Retrieve the current 3D object as a vtkPolyData.
virtual void GetAsMesh(vtkPolyData *out,const Properties& render_settings) const =0;

Expand Down Expand Up @@ -230,6 +235,8 @@ class AbstractRD
double x_spacing_proportion; /// spatial separation for rendering multiple chemicals, as a proportion of X
double y_spacing_proportion; /// spatial separation for rendering multiple chemicals, as a proportion of Y

Accuracy accuracy;

protected: // functions

/// Advance the RD system by n timesteps.
Expand Down
23 changes: 20 additions & 3 deletions src/readybase/FormulaOpenCLImageRD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,13 @@ struct InputsNeeded {

// -------------------------------------------------------------------------

InputsNeeded DetectInputsNeeded(const string& formula, int num_chemicals, int dimensionality, const int block_size[3])
InputsNeeded DetectInputsNeeded(const string& formula, int num_chemicals, int dimensionality, const int block_size[3],
const AbstractRD::Accuracy& accuracy)
{
InputsNeeded inputs_needed;

const vector<string> formula_tokens = tokenize_for_keywords(formula);
const vector<Stencil> known_stencils = GetKnownStencils(dimensionality);
const vector<Stencil> known_stencils = GetKnownStencils(dimensionality, accuracy);
for (int i = 0; i < num_chemicals; i++)
{
const string chem = GetChemicalName(i);
Expand Down Expand Up @@ -570,7 +571,7 @@ string FormulaOpenCLImageRD::AssembleKernelSourceFromFormula(const string& formu
}

const InputsNeeded inputs_needed = DetectInputsNeeded(formula, this->GetNumberOfChemicals(),
this->GetArenaDimensionality(), this->block_size);
this->GetArenaDimensionality(), this->block_size, this->GetAccuracy());

const string indent = " ";
const KernelOptions options(this->wrap, indent, this->data_type, full_data_type_string, this->data_type_suffix, this->block_size,
Expand Down Expand Up @@ -616,6 +617,20 @@ void FormulaOpenCLImageRD::InitializeFromXML(vtkXMLDataElement *rd, bool &warn_t
// number_of_chemicals:
read_required_attribute(xml_formula,"number_of_chemicals",this->n_chemicals);

// accuracy
string accuracy_string;
read_optional_attribute(xml_formula, "accuracy", accuracy_string);
if (accuracy_string.size() > 0)
{
const char* accuracy_labels[3] = { "low", "medium", "high" };
auto it = find(accuracy_labels, accuracy_labels + 3, accuracy_string);
if (it == accuracy_labels + 3)
{
throw std::runtime_error("unknown accuracy attribute: " + accuracy_string);
}
this->SetAccuracy(static_cast<AbstractRD::Accuracy>(it - accuracy_labels));
}

string formula = trim_multiline_string(xml_formula->GetCharacterData());
//this->TestFormula(formula); // will throw on error
this->SetFormula(formula); // (won't throw yet)
Expand All @@ -637,6 +652,8 @@ vtkSmartPointer<vtkXMLDataElement> FormulaOpenCLImageRD::GetAsXML(bool generate_
formula->SetIntAttribute("block_size_x", this->block_size[0]);
formula->SetIntAttribute("block_size_y", this->block_size[1]);
formula->SetIntAttribute("block_size_z", this->block_size[2]);
const char* accuracy_labels[3] = { "low", "medium", "high" };
formula->SetAttribute("accuracy", accuracy_labels[static_cast<int>(this->accuracy)]);
string f = this->GetFormula();
f = ReplaceAllSubstrings(f, "\n", "\n "); // indent the lines
formula->SetCharacterData(f.c_str(), (int)f.length());
Expand Down
3 changes: 3 additions & 0 deletions src/readybase/FormulaOpenCLImageRD.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ class FormulaOpenCLImageRD : public OpenCLImageRD
void SetBlockSizeY(int n) override { this->block_size[1] = n; this->need_reload_formula = true; }
void SetBlockSizeZ(int n) override { this->block_size[2] = n; this->need_reload_formula = true; }

bool HasEditableAccuracyOption() const override { return true; }
void SetAccuracy(Accuracy acc) override { this->accuracy = acc; this->need_reload_formula = true; }

std::string AssembleKernelSourceFromFormula(const std::string& formula) const override;

// we override the parameter access functions because changing the parameters requires rewriting the kernel
Expand Down
Loading

0 comments on commit c3ebc36

Please sign in to comment.