Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CvodeBlock and CvodeVisitor #1467

Draft
wants to merge 22 commits into
base: master
Choose a base branch
from
Draft

Add CvodeBlock and CvodeVisitor #1467

wants to merge 22 commits into from

Conversation

JCGoran
Copy link
Contributor

@JCGoran JCGoran commented Sep 24, 2024

Part 1 of #1399.
Adds the original DERIVATIVE block since NMODL solves it in-place. Also adds a visitors which actually replaces statements of the form x' = f(x) into Dx = f(x).

@JCGoran JCGoran changed the title Add DerivativeOriginalFunctionBlock and DerivativeVisitor Add DerivativeOriginalFunctionBlock and DerivativeOriginalVisitor Sep 24, 2024
bbpadministrator pushed a commit to BlueBrain/nmodl-references that referenced this pull request Sep 24, 2024
@JCGoran JCGoran marked this pull request as ready for review September 24, 2024 18:04
Copy link
Collaborator

@1uc 1uc left a comment

Choose a reason for hiding this comment

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

Two comments:

  • The DerivativeOriginalBlock is advertised as an unmodified copy. However, it's immediately during the process it's being modified.
  • There's no code demonstrating how this works, i.e. no tests or anything similar.

class DerivativeOriginalVisitor: public AstVisitor {
private:
/// The copy of the derivative block we are solving
ast::DerivativeBlock* der_block_function = nullptr;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why is this a _function?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since there's two blocks that will be added: one for Dx = f(x) (the _function one), and the other one for Dx = Dx / (1 - dt * J(f)) (the _jacobian, will be added in next breakdown of the original PR). I've debated about only adding one block, but the codegen would then require parsing the AST and modifying it, which I feel shouldn't be done at the codegen stage, hence the "two blocks, one visitor" design (the one visitor is here only because it felt pointless to make another one which does almost the same thing).

src/visitors/derivative_original_visitor.hpp Outdated Show resolved Hide resolved
src/visitors/derivative_original_visitor.cpp Outdated Show resolved Hide resolved
src/visitors/derivative_original_visitor.cpp Outdated Show resolved Hide resolved
src/language/codegen.yaml Outdated Show resolved Hide resolved
@@ -87,7 +87,30 @@
type: StatementBlock
- finalize_block:
brief: "Statement block to be executed after calling linear solver"
type: StatementBlock
type: StatementBlock
- DerivativeOriginalFunctionBlock:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why the Function in DerivativeOriginalFunctionBlock?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

NMODL doesn't allow two blocks with the same type (doesn't matter that they may not have the same name), and we will need another block for the transformation involving the Jacobian, so it's basically with that in mind that there's the additional Function. Open to suggestions on how to make it shorter though!

bbpadministrator pushed a commit to BlueBrain/nmodl-references that referenced this pull request Sep 25, 2024
`DERIVATIVE` blocks can't have array variables in NOCMODL by default, so
let's go with that.
bbpadministrator pushed a commit to BlueBrain/nmodl-references that referenced this pull request Sep 25, 2024
@JCGoran JCGoran changed the title Add DerivativeOriginalFunctionBlock and DerivativeOriginalVisitor Add CvodeBlock and CvodeVisitor Sep 27, 2024
bbpadministrator pushed a commit to BlueBrain/nmodl-references that referenced this pull request Sep 27, 2024
*/

/**
* \class DerivativeOriginalVisitor
Copy link
Collaborator

Choose a reason for hiding this comment

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

There's still a couple of places where the old term DerivativeOriginal exists (including filenames).

class CvodeVisitor: public AstVisitor {
private:
/// The copy of the derivative block we are solving
std::shared_ptr<ast::DerivativeBlock> der_block = nullptr;
Copy link
Collaborator

Choose a reason for hiding this comment

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

The abbreviation is slightly jarring.

std::shared_ptr<ast::DerivativeBlock> der_block = nullptr;

/// true while visiting differential equation
bool differential_equation = false;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Are the names for differential_equation and derivative_block idiomatic? Could they have a better name? Something the hints better at what they are: inside_*, beneath_*, is_*, printing_*

auto ast = run_cvode_visitor(nmodl_text);
THEN("CVODE block is added") {
auto block = collect_nodes(*ast, {ast::AstNodeType::CVODE_BLOCK});
REQUIRE(!block.empty());
Copy link
Collaborator

Choose a reason for hiding this comment

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

It has too be exactly one I think. At least it looks like that's the assumption further down.

)";
auto ast = run_cvode_visitor(nmodl_text);
THEN("CVODE block is added") {
auto block = collect_nodes(*ast, {ast::AstNodeType::CVODE_BLOCK});
Copy link
Collaborator

Choose a reason for hiding this comment

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

It's a vector of all CVODE_BLOCKs. Hence plural, blocks (or cvode_blocks); then later you'd be free to use block = block[0] (not much use).

}

// re-visit the AST since we now inserted the DERIVATIVE_ORIGINAL block
node.visit_children(*this);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why do we need to revisit them again?

Comment on lines 69 to 76
program_symtab = node.get_symbol_table();
node.visit_children(*this);
if (der_block) {
auto der_node = new ast::CvodeBlock(der_block->get_name(),
der_block->get_statement_block(),
der_block->get_statement_block());
node.emplace_back_node(der_node);
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

If you don't like the pattern that you need to toggle two booleans there's a way out. The code I marked essentially does a:

        auto blocks = collect_nodes(*ast, {ast::AstNodeType::DERIVATIVE_BLOCK});

Then all you need to do is run the {}' -> d{} replacement visitor (which consists of the visit_binary_expression) on each block and put them into CVodeBlocks and add them to the program.

Then there's no more boolean toggling; and it'll be more explicit about handling multiple DERIVATIVE blocks. BTW, the name for toggling being inside a cvode block is now rather misleading.

@JCGoran JCGoran marked this pull request as draft September 30, 2024 08:08
@JCGoran JCGoran mentioned this pull request Oct 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants