diff --git a/404.html b/404.html index e468cb1..a64cb32 100644 --- a/404.html +++ b/404.html @@ -52,6 +52,7 @@ + diff --git a/code-of-conduct.html b/code-of-conduct.html index 94e677e..137814a 100644 --- a/code-of-conduct.html +++ b/code-of-conduct.html @@ -52,6 +52,7 @@ + @@ -445,16 +446,17 @@
Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported to the community leaders responsible for enforcement anonymously using this [form] (https://forms.gle/2DnPXuCKKCN3qp7ZA).
-Reports will be -reviewed by a member of the NOAA Fisheries Office of Science and -Technology who is not participating in the FIMS Project [Patrick Lynch], +reported to the community leaders responsible for enforcement anonymously using +this form.
+Reports will be reviewed by a member of the NOAA Fisheries Office of Science +and Technology who is not participating in the FIMS Project [Patrick Lynch] but has the full support of FIMS Community Leaders. All reports will be reviewed promptly and fairly.
All community leaders are obligated to respect the privacy and security of the reporter of any incident whenever possible; however, please note behaviors that -meet the official criteria for harrassment must be reported by supervisors under -NOAA policy.
+meet the official +criteria +for harrassment must be reported by supervisors under NOAA policy.External contributions and feedback are important to the development and future maintenance of FIMS and are welcome. This section provides guidelines and workflows for FIMS developers and collaborators on how to contribute to the project.
The FIMS project uses style guides to ensure our code is consistent, easy to use (e.g. read, share, and verify), and ultimately easier to write. We use the Google C++ Style Guide and the tidyverse style guide for R code.
+The FIMS project uses style guides to ensure our code is consistent, easy to use (e.g., read, share, and verify), and ultimately easier to write. We use the Google C++ Style Guide and the tidyverse style guide for R code.
The FIMS implementation team has chosen to use typename
instead of class
when defining templates for consistency with the TMB
package. While types may be defined in many ways, for consistency developers are asked to use Type
instead of T
to define Type
s within FIMS.
The FIMS implementation team has chosen to use typename
instead of class
when defining templates for consistency with the TMB
package. While types may be defined in many ways, for consistency developers are asked to use Type
instead of T` to define Types within FIMS.
Following good software development and coding practices simplifies collaboration, improves readability, and streamlines testing and review. The following are industry-accepted standards:
evaluate()
) that are not specific to the type of
+methods (e.g., evaluate()
) that are not specific to the type of
functions available under the subfolders but reused for all objects of
that class type.
For contributors with write access to the FIMS repo, changes should be made on a feature branch after cloning the repo. The FIMS repo can be cloned to a local machine by using on the command line:
- +Bugs are tracked as GitHub issues. Create an issue on the toolbox Github repository and provide the following information by following the steps outlined in the reprex package. Explain the problem and include additional details to help maintainers reproduce the problem using the Bug Report issue template.
Provide more context by answering these questions:
Include details about your configuration and environment:
The following suggestions will help ensure optimal performance of the trunk-based branching strategy:
$ git checkout -b <branchname> main #creates a local branch
-$ git push origin <branchname> #pushes branch back to gitHub
$ git checkout -b <branchname> main #creates a local branch
+$ git push origin <branchname> #pushes branch back to gitHub
After which, changes can be pushed as:
- +Reviewers of PRs for changes to the codebase in FIMS should be @@ -812,8 +813,8 @@
To improve the plot viewer when creating plots in R
, install the httpgd
package:
To add syntax highlighting and other features to the R terminal, radian can be installed. Note needs to be installed first in order to download radian.
@@ -434,50 +435,50 @@{
- // Associate .RMD files with markdown:
- "files.associations": {
- "*.Rmd": "markdown",
- },
- // A cmake setting
- "cmake.configureOnOpen": true,
- // Set where the rulers are, needed for Rewrap. 72 is the default we have
- // decided on for FIMS repositories.z
- "editor.rulers": [
- 72
- ],
- // Should the editor suggest inline edits?
- "editor.inlineSuggest.enabled": true,
- // Settings for github copilot and which languages to use it with or not.
- "github.copilot.enable": {
- "*": true,
- "yaml": false,
- "plaintext": false,
- "markdown": false,
- "latex": false,
- "r": false
- },
- // Setting for sending R code from the editor to the terminal
- "r.alwaysUseActiveTerminal": true,
- // Needed to send large chunks of code to the r terminal when using radian
- "r.bracketedPaste": true,
- // Needed to use httpgd for plotting in vscode
- "r.plot.useHttpgd": true,
- // path to the r terminal (in this case, radian). Necessary to get the terminal to use radian.
- "r.rterm.windows": "C://Users//my.name//AppData//Local//Programs//Python//Python310//Scripts//radian.exe", //Use this only for Windows
- // options for the r terminal
- "r.rterm.option": [
- "--no-save",
- "--no-restore",
- "max.print=500"
- ],
- // Setting for whether to allow linting of documents or not
- "r.lsp.diagnostics": true,
- // When looking at diffs under the version control tab, should whitspace be ignored?
- "diffEditor.ignoreTrimWhitespace": false,
- // What is the max number of lines that are printed as output to the terminal?
- "terminal.integrated.scrollback": 10000
-}
{
+ // Associate .RMD files with markdown:
+ "files.associations": {
+ "*.Rmd": "markdown",
+ },
+ // A cmake setting
+ "cmake.configureOnOpen": true,
+ // Set where the rulers are, needed for Rewrap. 72 is the default we have
+ // decided on for FIMS repositories.z
+ "editor.rulers": [
+ 72
+ ],
+ // Should the editor suggest inline edits?
+ "editor.inlineSuggest.enabled": true,
+ // Settings for github copilot and which languages to use it with or not.
+ "github.copilot.enable": {
+ "*": true,
+ "yaml": false,
+ "plaintext": false,
+ "markdown": false,
+ "latex": false,
+ "r": false
+ },
+ // Setting for sending R code from the editor to the terminal
+ "r.alwaysUseActiveTerminal": true,
+ // Needed to send large chunks of code to the r terminal when using radian
+ "r.bracketedPaste": true,
+ // Needed to use httpgd for plotting in vscode
+ "r.plot.useHttpgd": true,
+ // path to the r terminal (in this case, radian). Necessary to get the terminal to use radian.
+ "r.rterm.windows": "C://Users//my.name//AppData//Local//Programs//Python//Python310//Scripts//radian.exe", //Use this only for Windows
+ // options for the r terminal
+ "r.rterm.option": [
+ "--no-save",
+ "--no-restore",
+ "max.print=500"
+ ],
+ // Setting for whether to allow linting of documents or not
+ "r.lsp.diagnostics": true,
+ // When looking at diffs under the version control tab, should whitspace be ignored?
+ "diffEditor.ignoreTrimWhitespace": false,
+ // What is the max number of lines that are printed as output to the terminal?
+ "terminal.integrated.scrollback": 10000
+}
Some suggested R shortcuts could be helpful.
@@ -513,19 +514,19 @@gcc: fatal error: no input files compilation
-terminated.
+
If not, you will need to check that the compiler is on the path. The easiest way to do so is by creating a text file .Renviron in your Documents folder which contains the following line:
PATH="${RTOOLS44_HOME}\usr\bin;${PATH}"
You can do this with a text editor, or from R
like so (note that in
R
code you need to escape backslashes):
Restart R, and verify that make can be found, which should show the path to your Rtools installation.
- +cmake -S. -B build -G Ninja
-cmake -- build build
graph TD
- A -- R interface group --> C[short-lived feature branch];
- A -- Documentation group --> D[short-lived feature branch];
- A -- NLL group --> E[development branch];
- A -- More features group --> E[development branch];
- E --> F[short-lived feature branch];
- C --> G[Merge into main];
- D --> G;
- F --> E;
- E --> G;
+
+
In this section we will describe how to structure a new .hpp file in FIMS.
-// tmplate.hpp
-// Fisheries Integrated Modeling System (FIMS)
-
-//define the header gaurd
-#ifndef template_hpp
-#define template_hpp
-
-//inherit from model_base
-#include "../common.hpp"
-#include <iostream>
-
-/**
- * In this example, we utilize the concept of inheritence and
- * polymorphism (https://www.geeksforgeeks.org/polymorphism-in-c/). All
- * classes inherit from model_base. Name1 and Name2 inherit from NameBase.
- * Classes Name1 and Name2 must implement they're own version of
- * "virtual T evaluate(const T& t)", which will have unique logic.
- */
-
-
-/*
- * fims namespace
- */
-namespace fims{
-
-/**
- * NameBase class. Inherits from model_base.
- */
-template <class T>
-class NameBase: public model_base<T>{ //note that model_base gets template parameter T.
-protected:
-
-public:
- virtual T Evaluate(const T& t)=0; //"= 0;" means this must be implemented in child.
-};
-
-/*
-* Template class inherits from NameBase
-*/
-template <class T>
-class Name1: public NameBase<T>{
-
-public:
-
-
- /*
- *Default constructor
- *Initialize any memory here.
- */
- Name1(){
- }
-
-
- /**
- * Destructor; this method destructs Name1 object.
- * Delete any allocated memory here.
- */
- ~ Name1(){
- std::cout <<"I just deleted Name1 object" << std::endl;
- }
-
- /**
- * Note: this function must have the same signature as evaluate in NameBase.
- * Overloaded virtual function. This is polymorphism, meaning the
- * signature has the same appearance, but the function itself has unique logic.
- *
- * @param t
- * @return t+1
- */
- virtual T Evaluate(const T& t) {
- std::cout<<"evaluate in Name1 received "<<t<<
- "as a method parameter, returning "<<(t+1)<<std::endl;
- return t+1; //unique logic for Name1 class
- }
-
-};
-
- /*
-* Template class inherits from NameBase
-*/
-template <class T>
-class Name2: public NameBase<T>{
-
-public:
-
-
- /*
- *Default constructor.
- *Initialize any memory here.
- */
- Name2(){
- }
-
-
- /**
- * Destructor; this method destructs the Name2 object.
- * Delete any allocated memory here.
- */
- ~ Name2(){
- std::cout <<"I just deleted Name2 object" << std::endl;
- }
-
- /**
- * Note: this function must have the same signature as evaluate in NameBase.
- * Overloaded virtual function. This is polymorphism, meaning the
- * signature has the same appearance, but the function itself has unique logic.
- *
- * @param t
- * @return t^2
- */
- virtual T Evaluate(const T& t) {
- std::cout<<"evaluate in Name2 received "<<t<<
- "as a method parameter, returning "<<(t*t)<<std::endl;
- return t*t; //unique logic for Name2 class
- }
-
-};
-
-/**
- * Add additional implementations below.
- */
-
-
-
-
-} //end namespace
-
-/**
- *Example usage:
- *
- * void main(int argc, char** argv){
- * NameBase<double>* name = NULL; //pointer to a NameBase object
- * Name1<double> n1; //inherits from NameBase
- * Name2<double> n2; //inherits from NameBase
- *
- * name = &n1; //name now points to n1
- * name->Evalute(2.0); //unique logic for n1
- *
- * name = &n2; //name now points to n2
- * name->Evalute(2.0); //unique logic for n2
- * }
- *
- * Output:
- * evaluate in Name1 received 2 as a method parameter, returning 3
- * evaluate in Name2 received 2 as a method parameter, returning 4
- *
- */
-
-
-
-#endif /*template_hpp */
// tmplate.hpp
+// Fisheries Integrated Modeling System (FIMS)
+
+//define the header gaurd
+#ifndef template_hpp
+#define template_hpp
+
+//inherit from model_base
+#include "../common.hpp"
+#include <iostream>
+
+/**
+ * In this example, we utilize the concept of inheritence and
+ * polymorphism (https://www.geeksforgeeks.org/polymorphism-in-c/). All
+ * classes inherit from model_base. Name1 and Name2 inherit from NameBase.
+ * Classes Name1 and Name2 must implement they're own version of
+ * "virtual T evaluate(const T& t)", which will have unique logic.
+ */
+
+
+/*
+ * fims namespace
+ */
+namespace fims{
+
+/**
+ * NameBase class. Inherits from model_base.
+ */
+template <class T>
+class NameBase: public model_base<T>{ //note that model_base gets template parameter T.
+protected:
+
+public:
+ virtual T Evaluate(const T& t)=0; //"= 0;" means this must be implemented in child.
+};
+
+/*
+* Template class inherits from NameBase
+*/
+template <class T>
+class Name1: public NameBase<T>{
+
+public:
+
+
+ /*
+ *Default constructor
+ *Initialize any memory here.
+ */
+ Name1(){
+ }
+
+
+ /**
+ * Destructor; this method destructs Name1 object.
+ * Delete any allocated memory here.
+ */
+ ~ Name1(){
+ std::cout <<"I just deleted Name1 object" << std::endl;
+ }
+
+ /**
+ * Note: this function must have the same signature as evaluate in NameBase.
+ * Overloaded virtual function. This is polymorphism, meaning the
+ * signature has the same appearance, but the function itself has unique logic.
+ *
+ * @param t
+ * @return t+1
+ */
+ virtual T Evaluate(const T& t) {
+ std::cout<<"evaluate in Name1 received "<<t<<
+ "as a method parameter, returning "<<(t+1)<<std::endl;
+ return t+1; //unique logic for Name1 class
+ }
+
+};
+
+ /*
+* Template class inherits from NameBase
+*/
+template <class T>
+class Name2: public NameBase<T>{
+
+public:
+
+
+ /*
+ *Default constructor.
+ *Initialize any memory here.
+ */
+ Name2(){
+ }
+
+
+ /**
+ * Destructor; this method destructs the Name2 object.
+ * Delete any allocated memory here.
+ */
+ ~ Name2(){
+ std::cout <<"I just deleted Name2 object" << std::endl;
+ }
+
+ /**
+ * Note: this function must have the same signature as evaluate in NameBase.
+ * Overloaded virtual function. This is polymorphism, meaning the
+ * signature has the same appearance, but the function itself has unique logic.
+ *
+ * @param t
+ * @return t^2
+ */
+ virtual T Evaluate(const T& t) {
+ std::cout<<"evaluate in Name2 received "<<t<<
+ "as a method parameter, returning "<<(t*t)<<std::endl;
+ return t*t; //unique logic for Name2 class
+ }
+
+};
+
+/**
+ * Add additional implementations below.
+ */
+
+
+
+
+} //end namespace
+
+/**
+ *Example usage:
+ *
+ * void main(int argc, char** argv){
+ * NameBase<double>* name = NULL; //pointer to a NameBase object
+ * Name1<double> n1; //inherits from NameBase
+ * Name2<double> n2; //inherits from NameBase
+ *
+ * name = &n1; //name now points to n1
+ * name->Evalute(2.0); //unique logic for n1
+ *
+ * name = &n2; //name now points to n2
+ * name->Evalute(2.0); //unique logic for n2
+ * }
+ *
+ * Output:
+ * evaluate in Name1 received 2 as a method parameter, returning 3
+ * evaluate in Name2 received 2 as a method parameter, returning 4
+ *
+ */
+
+
+
+#endif /*template_hpp */
To use GoogleTest, you will need:
A compatible operating system (e.g. Windows, masOS, or Linux).
A compatible operating system (e.g., Windows, masOS, or Linux).
A C++ compiler that supports at least C++ 11 standard or newer (e.g. gcc 5.0+, clang 5.0+, or MSVC 2015+). For macOS users, Xcode 9.3+ provides clang 5.0. For R users, @@ -507,8 +508,8 @@
Clone the FIMS repository on the command line using:
- +There is a file called CMakeLists.txt in the top level of the directory. This file instructs Cmake on how to create the build files, including setting up Google Test.
@@ -520,71 +521,71 @@Three commands on the command line are needed to build the tests:
- +This generates the build system using Ninja as the generator. Note there is now a subfolder called build.
Next, in the same command window, use cmake to build in the build subfolder:
- +Finally, run the C++ tests:
- +The output from running the tests should look something like:
-Internal ctest changing into directory: C:/github_repos/NOAA-FIMS_org/FIMS/build
-Test project C:/github_repos/NOAA-FIMS_org/FIMS/build
- Start 1: dlognorm.use_double_inputs
-1/5 Test #1: dlognorm.use_double_inputs ....... Passed 0.04 sec
- Start 2: dlognorm.use_int_inputs
-2/5 Test #2: dlognorm.use_int_inputs .......... Passed 0.04 sec
- Start 3: modelTest.eta
-3/5 Test #3: modelTest.eta .................... Passed 0.04 sec
- Start 4: modelTest.nll
-4/5 Test #4: modelTest.nll .................... Passed 0.04 sec
- Start 5: modelTest.evaluate
-5/5 Test #5: modelTest.evaluate ............... Passed 0.04 sec
-
-100% tests passed, 0 tests failed out of 5
Internal ctest changing into directory: C:/github_repos/NOAA-FIMS_org/FIMS/build
+Test project C:/github_repos/NOAA-FIMS_org/FIMS/build
+ Start 1: dlognorm.use_double_inputs
+1/5 Test #1: dlognorm.use_double_inputs ....... Passed 0.04 sec
+ Start 2: dlognorm.use_int_inputs
+2/5 Test #2: dlognorm.use_int_inputs .......... Passed 0.04 sec
+ Start 3: modelTest.eta
+3/5 Test #3: modelTest.eta .................... Passed 0.04 sec
+ Start 4: modelTest.nll
+4/5 Test #4: modelTest.nll .................... Passed 0.04 sec
+ Start 5: modelTest.evaluate
+5/5 Test #5: modelTest.evaluate ............... Passed 0.04 sec
+
+100% tests passed, 0 tests failed out of 5
Create a file dlognorm.hpp within the src subfolder that contains a simple function:
-#include <cmath>
-
-template<class Type>
-Type dlognorm(Type x, Type meanlog, Type sdlog){
- Type resid = (log(x)-meanlog)/sdlog;
- Type logres = -log(sqrt(2*M_PI)) - log(sdlog) - Type(0.5)*resid*resid - log(x);
- return logres;
-}
#include <cmath>
+
+template<class Type>
+Type dlognorm(Type x, Type meanlog, Type sdlog){
+ Type resid = (log(x)-meanlog)/sdlog;
+ Type logres = -log(sqrt(2*M_PI)) - log(sdlog) - Type(0.5)*resid*resid - log(x);
+ return logres;
+}
Then, create a test file dlognorm-unit.cpp in the tests/gtest subfolder that has a test suite for the dlognorm function:
-#include "gtest/gtest.h"
-#include "../../src/dlognorm.hpp"
-
-// # R code that generates true values for the test
-// dlnorm(1.0, 0.0, 1.0, TRUE) = -0.9189385
-// dlnorm(5.0, 10.0, 2.5, TRUE) = -9.07679
-
-namespace {
-
- // TestSuiteName: dlognormTest; TestName: DoubleInput and IntInput
- // Test dlognorm with double input values
-
- TEST(dlognormTest, DoubleInput) {
-
- EXPECT_NEAR( dlognorm(1.0, 0.0, 1.0) , -0.9189385 , 0.0001 );
- EXPECT_NEAR( dlognorm(5.0, 10.0, 2.5) , -9.07679 , 0.0001 );
-
- }
-
- // Test dlognorm with integer input values
-
- TEST(dlognormTest, IntInput) {
-
- EXPECT_NEAR( dlognorm(1, 0, 1) , -0.9189385 , 0.0001 );
-
- }
-
-}
#include "gtest/gtest.h"
+#include "../../src/dlognorm.hpp"
+
+// # R code that generates true values for the test
+// dlnorm(1.0, 0.0, 1.0, TRUE) = -0.9189385
+// dlnorm(5.0, 10.0, 2.5, TRUE) = -9.07679
+
+namespace {
+
+ // TestSuiteName: dlognormTest; TestName: DoubleInput and IntInput
+ // Test dlognorm with double input values
+
+ TEST(dlognormTest, DoubleInput) {
+
+ EXPECT_NEAR( dlognorm(1.0, 0.0, 1.0) , -0.9189385 , 0.0001 );
+ EXPECT_NEAR( dlognorm(5.0, 10.0, 2.5) , -9.07679 , 0.0001 );
+
+ }
+
+ // Test dlognorm with integer input values
+
+ TEST(dlognormTest, IntInput) {
+
+ EXPECT_NEAR( dlognorm(1, 0, 1) , -0.9189385 , 0.0001 );
+
+ }
+
+}
EXPECT_NEAR(val1, val2, absolute_error)
verifies that the difference
between val1
and val2
does not exceed the absolute error bound
absolute_error
. EXPECT_NE(val1, val2)
verifies that val1
is not
@@ -595,88 +596,88 @@
tests/gtest/CMakeLists.txt
and run a binaryTo build the code, add the following contents to the end of the tests/gtest/CMakeLists.txt
file:
-add_executable(dlognorm_test
- dlognorm-unit.cpp
-)
-
-target_include_directories(dlognorm_test
- PUBLIC
- ${CMAKE_SOURCE_DIR}/../
-)
-
-target_link_libraries(dlognorm_test
- gtest_main
-)
-
-include(GoogleTest)
-gtest_discover_tests(dlognorm_test)
+add_executable(dlognorm_test
+ dlognorm-unit.cpp
+)
+
+target_include_directories(dlognorm_test
+ PUBLIC
+ ${CMAKE_SOURCE_DIR}/../
+)
+
+target_link_libraries(dlognorm_test
+ gtest_main
+)
+
+include(GoogleTest)
+gtest_discover_tests(dlognorm_test)
The above configuration enables testing in CMake, declares the C++ test binary you want to build (dlognorm_test), and links it to GoogleTest (gtest_main). Now you can build and run your test. Open a command window in the FIMS repo (if not already opened) and type:
- +This generates the build system using Ninja as the generator.
Next, in the same command window, use cmake to build:
- +Finally, run the tests in the same command window:
- +The output when running ctest
might look like this. Note there is a
failing test:
Internal ctest changing into directory: C:/Users/Kathryn.Doering/Documents/testing/FIMS/build
-Test project C:/Users/Kathryn.Doering/Documents/testing/FIMS/build
- Start 1: dlognorm.use_double_inputs
-1/7 Test #1: dlognorm.use_double_inputs ....... Passed 0.04 sec
- Start 2: dlognorm.use_int_inputs
-2/7 Test #2: dlognorm.use_int_inputs .......... Passed 0.04 sec
- Start 3: modelTest.eta
-3/7 Test #3: modelTest.eta .................... Passed 0.04 sec
- Start 4: modelTest.nll
-4/7 Test #4: modelTest.nll .................... Passed 0.04 sec
- Start 5: modelTest.evaluate
-5/7 Test #5: modelTest.evaluate ............... Passed 0.04 sec
- Start 6: dlognormTest.DoubleInput
-6/7 Test #6: dlognormTest.DoubleInput ......... Passed 0.04 sec
- Start 7: dlognormTest.IntInput
-7/7 Test #7: dlognormTest.IntInput ............***Failed 0.04 sec
-
-86% tests passed, 1 tests failed out of 7
-
-Total Test time (real) = 0.28 sec
-
-The following tests FAILED:
- 7 - dlognormTest.IntInput (Failed)
-Errors while running CTest
-Output from these tests are in: C:/Users/Kathryn.Doering/Documents/testing/FIMS/build/Testing/Temporary/LastTest.log
-Use "--rerun-failed --output-on-failure" to re-run the failed cases verbosely.
Internal ctest changing into directory: C:/Users/Kathryn.Doering/Documents/testing/FIMS/build
+Test project C:/Users/Kathryn.Doering/Documents/testing/FIMS/build
+ Start 1: dlognorm.use_double_inputs
+1/7 Test #1: dlognorm.use_double_inputs ....... Passed 0.04 sec
+ Start 2: dlognorm.use_int_inputs
+2/7 Test #2: dlognorm.use_int_inputs .......... Passed 0.04 sec
+ Start 3: modelTest.eta
+3/7 Test #3: modelTest.eta .................... Passed 0.04 sec
+ Start 4: modelTest.nll
+4/7 Test #4: modelTest.nll .................... Passed 0.04 sec
+ Start 5: modelTest.evaluate
+5/7 Test #5: modelTest.evaluate ............... Passed 0.04 sec
+ Start 6: dlognormTest.DoubleInput
+6/7 Test #6: dlognormTest.DoubleInput ......... Passed 0.04 sec
+ Start 7: dlognormTest.IntInput
+7/7 Test #7: dlognormTest.IntInput ............***Failed 0.04 sec
+
+86% tests passed, 1 tests failed out of 7
+
+Total Test time (real) = 0.28 sec
+
+The following tests FAILED:
+ 7 - dlognormTest.IntInput (Failed)
+Errors while running CTest
+Output from these tests are in: C:/Users/Kathryn.Doering/Documents/testing/FIMS/build/Testing/Temporary/LastTest.log
+Use "--rerun-failed --output-on-failure" to re-run the failed cases verbosely.
There are two ways to debug a C++ test, interactively using gdb
or via print statements. To use gdb
, make sure it is installed and on your path.
Debug C++ code (e.g., segmentation error/memory corruption) using gdb:
-cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug
-cmake --build build --parallel 16
-ctest --test-dir build --parallel 16
-gdb ./build/tests/gtest/population_dynamics_population.exe
-c // to continue without paging
-run // to see which line of code is broken
-print this->log_naa // for example, print this->log_naa to see the value of log_naa;
-print i // for example, print i from the broken for loop
-bt // backtrace
-q // to quit
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug
+cmake --build build --parallel 16
+ctest --test-dir build --parallel 16
+gdb ./build/tests/gtest/population_dynamics_population.exe
+c // to continue without paging
+run // to see which line of code is broken
+print this->log_naa // for example, print this->log_naa to see the value of log_naa;
+print i // for example, print i from the broken for loop
+bt // backtrace
+q // to quit
Debug C++ code without using gdb:
Update code in a .hpp file by calling std::ofstream out(“file_name.txt”)
Then use out << variable;
to print out values of the variable
More complex examples with text identifying the quantities
-out <<" fleet_index: "<<fleet_index<<" index_yaf: "<<index_yaf<<" index_yf: "<<index_yf<<"\n";
-out <<" population.Fmort[index_yf]: "<<population.Fmort[index_yf]<<"\n";
out <<" fleet_index: "<<fleet_index<<" index_yaf: "<<index_yaf<<" index_yf: "<<index_yf<<"\n";
+out <<" population.Fmort[index_yf]: "<<population.Fmort[index_yf]<<"\n";
Git Bash
-cmake -S . -B build -G Ninja
-cmake --build build --parallel 16
-ctest --test-dir build --parallel 16
cmake -S . -B build -G Ninja
+cmake --build build --parallel 16
+ctest --test-dir build --parallel 16
The output of the print statements will be in this test file: FIMS/build/tests/gtest/debug.txt
#include "benchmark/benchmark.h"
-#include "../../src/dlognorm.hpp"
-
-void BM_dlgnorm(benchmark::State& state)
-{
- for (auto _ : state)
- dlognorm(5.0, 10.0, 2.5);
-}
-BENCHMARK(BM_dlgnorm);
#include "benchmark/benchmark.h"
+#include "../../src/dlognorm.hpp"
+
+void BM_dlgnorm(benchmark::State& state)
+{
+ for (auto _ : state)
+ dlognorm(5.0, 10.0, 2.5);
+}
+BENCHMARK(BM_dlgnorm);
This file runs the dlognorm function and uses BENCHMARK to see how long it takes.
A more comprehensive feature overview of benchmarking is available in @@ -703,51 +704,51 @@
tests/gtest/CMakeLists.txt
and run the benchmarkTo build the code, add the following contents to the end of your
tests/gtest/CMakeLists.txt
file:
-FetchContent_Declare(
- googlebenchmark
- URL https://github.com/google/benchmark/archive/refs/tags/v1.6.0.zip
-)
-FetchContent_MakeAvailable(googlebenchmark)
-
-add_executable(dlognorm_benchmark
- dlognorm_benchmark.cpp
-)
-
-target_include_directories(dlognorm_benchmark
- PUBLIC
- ${CMAKE_SOURCE_DIR}/../
-)
-
-target_link_libraries(dlognorm_benchmark
- benchmark_main
-)
+FetchContent_Declare(
+ googlebenchmark
+ URL https://github.com/google/benchmark/archive/refs/tags/v1.6.0.zip
+)
+FetchContent_MakeAvailable(googlebenchmark)
+
+add_executable(dlognorm_benchmark
+ dlognorm_benchmark.cpp
+)
+
+target_include_directories(dlognorm_benchmark
+ PUBLIC
+ ${CMAKE_SOURCE_DIR}/../
+)
+
+target_link_libraries(dlognorm_benchmark
+ benchmark_main
+)
To run the benchmark, open the command line open in the FIMS repo (if not already open) and run cmake, sending output to the build subfolder:
- +Then run the dlognorm_benchmark executable created:
- +The output from dlognorm_benchmark.exe
might look like this:
Run on (8 X 2112 MHz CPU s)
-CPU Caches:
- L1 Data 32 KiB (x4)
-L1 Instruction 32 KiB (x4)
-L2 Unified 256 KiB (x4)
-L3 Unified 8192 KiB (x1)
-***WARNING*** Library was built as DEBUG. Timings may be affected.
------------------------------------------------------
- Benchmark Time CPU Iterations
------------------------------------------------------
- BM_dlgnorm 153 ns 153 ns 4480000
Run on (8 X 2112 MHz CPU s)
+CPU Caches:
+ L1 Data 32 KiB (x4)
+L1 Instruction 32 KiB (x4)
+L2 Unified 256 KiB (x4)
+L3 Unified 8192 KiB (x1)
+***WARNING*** Library was built as DEBUG. Timings may be affected.
+-----------------------------------------------------
+ Benchmark Time CPU Iterations
+-----------------------------------------------------
+ BM_dlgnorm 153 ns 153 ns 4480000
If you don’t want to keep any of the files produced by this example and want to completely clear any uncommitted changes and files from the git repo, use
- +to get rid of un committed changes in git tracked files. To get rid of all untracked files in the repo, use:
- +#include "gtest/gtest.h"
-#include "../../src/code.hpp"
-
-// # R code that generates true values for the test
-
-namespace {
-
- // Description of Test 1
- TEST(TestSuiteName, Test1Name) {
-
- ... test body ...
-
- }
-
- // Description of Test 2
- TEST(TestSuiteName, Test2Name) {
-
- ... test body ...
-
- }
-
-}
#include "gtest/gtest.h"
+#include "../../src/code.hpp"
+
+// # R code that generates true values for the test
+
+namespace {
+
+ // Description of Test 1
+ TEST(TestSuiteName, Test1Name) {
+
+ ... test body ...
+
+ }
+
+ // Description of Test 2
+ TEST(TestSuiteName, Test2Name) {
+
+ ... test body ...
+
+ }
+
+}
These lines are added each time a new test suite (all tests in a file) is added:
-// Add test suite 1
-add_executable(TestSuiteName1
- test1.cpp
+// Add test suite 1
+add_executable(TestSuiteName1
+ test1.cpp
+)
+
+target_link_libraries(TestSuiteName1
+ gtest_main
+)
+
+gtest_discover_tests(TestSuiteName1)
+These lines are added each time a new benchmark file is added:
+// Add benchmark 1
+add_executable(benchmark1
+ benchmark1.cpp
)
-target_link_libraries(TestSuiteName1
- gtest_main
-)
-
-gtest_discover_tests(TestSuiteName1)
-These lines are added each time a new benchmark file is added:
-// Add benchmark 1
-add_executable(benchmark1
- benchmark1.cpp
-)
-
-target_link_libraries(benchmark1
- benchmark_main
-)
+target_link_libraries(benchmark1
+ benchmark_main
+)
gdbsource
You can interactively debug C++ code using TMB::gdbsource()
in RStudio. Just add these two lines to the top of the test-fims-estimation.R file
R
You can add components to the model using S4 classes.
- +