{"action":"created","comment":{"url":"https://api.github.com/repos/nutofem/nuto/pulls/comments/189804755","pull_request_review_id":122052288,"id":189804755,"diff_hunk":"@@ -36,85 +36,115 @@ std::vector<DofType> DofIntersection(std::vector<DofType> one, std::vector<DofTy\n }\n \n DofVector<double> SimpleAssembler::BuildVector(const Group<CellInterface>& cells, std::vector<DofType> dofTypes,\n-                                             CellInterface::VectorFunction f) const\n+                                               CellInterface::VectorFunction f) const\n {\n     ThrowOnZeroDofNumbering(dofTypes);\n \n     DofVector<double> gradient = ProperlyResizedVector(dofTypes);\n-    for (NuTo::CellInterface& cell : cells)\n-    {\n-        const DofVector<double> cellGradient = cell.Integrate(f);\n \n-        for (DofType dof : DofIntersection(cellGradient.DofTypes(), dofTypes))\n+#pragma omp parallel\n+    {\n+        DofVector<double> threadlocalgradient = ProperlyResizedVector(dofTypes);\n+#pragma omp for nowait\n+        for (auto cellit = cells.begin(); cellit < cells.end(); cellit++)\n         {\n-            Eigen::VectorXi numberingDof = cell.DofNumbering(dof);\n-            const Eigen::VectorXd& cellGradientDof = cellGradient[dof];\n-            for (int i = 0; i < numberingDof.rows(); ++i)\n-                gradient[dof](numberingDof[i]) += cellGradientDof[i];\n+            const DofVector<double> cellGradient = cellit->Integrate(f);\n+\n+            for (DofType dof : DofIntersection(cellGradient.DofTypes(), dofTypes))\n+            {\n+                Eigen::VectorXi numberingDof = cellit->DofNumbering(dof);\n+                const Eigen::VectorXd& cellGradientDof = cellGradient[dof];\n+                for (int i = 0; i < numberingDof.rows(); ++i)\n+                    threadlocalgradient[dof](numberingDof[i]) += cellGradientDof[i];\n+            }\n         }\n+#pragma omp critical\n+        gradient += threadlocalgradient;\n     }\n     return gradient;\n }\n \n DofVector<double> SimpleAssembler::BuildDiagonallyLumpedMatrix(const Group<CellInterface>& cells,\n-                                                             std::vector<DofType> dofTypes,\n-                                                             CellInterface::MatrixFunction f) const\n+                                                               std::vector<DofType> dofTypes,\n+                                                               CellInterface::MatrixFunction f) const\n {\n     DofVector<double> lumpedMatrix = ProperlyResizedVector(dofTypes);\n-    for (NuTo::CellInterface& cell : cells)\n-    {\n-        const DofMatrix<double> localMatrix = cell.Integrate(f);\n \n-        for (DofType dof : DofIntersection(localMatrix.DofTypes(), dofTypes))\n+#pragma omp parallel\n+    {\n+        DofVector<double> threadlocallumpedMatrix = ProperlyResizedVector(dofTypes);\n+#pragma omp for nowait\n+        for (auto cellit = cells.begin(); cellit < cells.end(); cellit++)\n         {\n-            Eigen::VectorXd localDiagonalDof = localMatrix(dof, dof).diagonal();\n-            double diagonalSum = localDiagonalDof.sum();\n-            double fullSum = localMatrix(dof, dof).sum();\n-            localDiagonalDof *= (fullSum / diagonalSum) / dof.GetNum();\n+            const DofMatrix<double> localMatrix = cellit->Integrate(f);\n+\n+            for (DofType dof : DofIntersection(localMatrix.DofTypes(), dofTypes))\n+            {\n+                Eigen::VectorXd localDiagonalDof = localMatrix(dof, dof).diagonal();\n+                double diagonalSum = localDiagonalDof.sum();\n+                double fullSum = localMatrix(dof, dof).sum();\n+                localDiagonalDof *= (fullSum / diagonalSum) / dof.GetNum();\n \n-            Eigen::VectorXi numberingDof = cell.DofNumbering(dof);\n+                Eigen::VectorXi numberingDof = cellit->DofNumbering(dof);\n \n-            for (int i = 0; i < numberingDof.rows(); ++i)\n-                lumpedMatrix[dof](numberingDof[i]) += localDiagonalDof[i];\n+                for (int i = 0; i < numberingDof.rows(); ++i)\n+                    threadlocallumpedMatrix[dof](numberingDof[i]) += localDiagonalDof[i];\n+            }\n         }\n+#pragma omp critical\n+        lumpedMatrix += threadlocallumpedMatrix;\n     }\n     return lumpedMatrix;\n }\n \n DofMatrixSparse<double> SimpleAssembler::BuildMatrix(const Group<CellInterface>& cells, std::vector<DofType> dofTypes,\n-                                                   CellInterface::MatrixFunction f) const\n+                                                     CellInterface::MatrixFunction f) const\n {\n     ThrowOnZeroDofNumbering(dofTypes);\n \n-    using TripletList = std::vector<Eigen::Triplet<double>>;\n+    using TripletList = std::list<Eigen::Triplet<double>>;\n     DofMatrixContainer<TripletList> triplets;\n \n-    for (NuTo::CellInterface& cell : cells)\n+#pragma omp parallel\n     {\n-        const DofMatrix<double> cellHessian = cell.Integrate(f);\n-        auto dofTypesToAssemble = DofIntersection(cellHessian.DofTypes(), dofTypes);\n+        DofMatrixContainer<TripletList> localtriplets;\n \n-        for (DofType dofI : dofTypesToAssemble)\n+#pragma omp for nowait\n+        for (auto cellit = cells.begin(); cellit < cells.end(); cellit++)\n         {\n-            Eigen::VectorXi numberingDofI = cell.DofNumbering(dofI);\n-            for (DofType dofJ : dofTypesToAssemble)\n-            {\n-                Eigen::VectorXi numberingDofJ = cell.DofNumbering(dofJ);\n-                const Eigen::MatrixXd& cellHessianDof = cellHessian(dofI, dofJ);\n+            const DofMatrix<double> cellHessian = cellit->Integrate(f);\n+            auto dofTypesToAssemble = DofIntersection(cellHessian.DofTypes(), dofTypes);\n \n-                for (int i = 0; i < numberingDofI.rows(); ++i)\n+            for (DofType dofI : dofTypesToAssemble)\n+            {\n+                Eigen::VectorXi numberingDofI = cellit->DofNumbering(dofI);\n+                for (DofType dofJ : dofTypesToAssemble)\n                 {\n-                    for (int j = 0; j < numberingDofJ.rows(); ++j)\n-                    {\n-                        const int globalDofNumberI = numberingDofI[i];\n-                        const int globalDofNumberJ = numberingDofJ[j];\n-                        const double globalDofValue = cellHessianDof(i, j);\n+                    Eigen::VectorXi numberingDofJ = cellit->DofNumbering(dofJ);\n+                    const Eigen::MatrixXd& cellHessianDof = cellHessian(dofI, dofJ);\n \n-                        triplets(dofI, dofJ).push_back({globalDofNumberI, globalDofNumberJ, globalDofValue});\n+                    for (int i = 0; i < numberingDofI.rows(); ++i)\n+                    {\n+                        for (int j = 0; j < numberingDofJ.rows(); ++j)\n+                        {\n+                            const int globalDofNumberI = numberingDofI[i];\n+                            const int globalDofNumberJ = numberingDofJ[j];\n+                            const double globalDofValue = cellHessianDof(i, j);\n+\n+                            localtriplets(dofI, dofJ).push_back({globalDofNumberI, globalDofNumberJ, globalDofValue});\n+                        }\n                     }\n                 }\n             }\n         }\n+#pragma omp critical\n+        {\n+            for (DofType dofI : dofTypes)\n+                for (DofType dofJ : dofTypes)\n+                {\n+                    triplets(dofI, dofJ).splice(triplets(dofI, dofJ).end(), localtriplets(dofI, dofJ));","path":"nuto/mechanics/cell/SimpleAssembler.cpp","position":150,"original_position":150,"commit_id":"7bd1a22c4ba31021bad7d2802d2d8c8921bf2ffb","original_commit_id":"8d93ba1ab01aa39d261f8a69d43f053eeeb9cb97","user":{"login":"pmueller2","id":24247180,"avatar_url":"https://avatars0.githubusercontent.com/u/24247180?v=4","gravatar_id":"","url":"https://api.github.com/users/pmueller2","html_url":"https://github.com/pmueller2","followers_url":"https://api.github.com/users/pmueller2/followers","following_url":"https://api.github.com/users/pmueller2/following{/other_user}","gists_url":"https://api.github.com/users/pmueller2/gists{/gist_id}","starred_url":"https://api.github.com/users/pmueller2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pmueller2/subscriptions","organizations_url":"https://api.github.com/users/pmueller2/orgs","repos_url":"https://api.github.com/users/pmueller2/repos","events_url":"https://api.github.com/users/pmueller2/events{/privacy}","received_events_url":"https://api.github.com/users/pmueller2/received_events","type":"User","site_admin":false},"body":"The bottleneck in the matrix assembly is the Eigen conversion from triplet lists to sparse matrix and since the simple assembler will vanish probably anyway I would just leave it as it is to have at least some parallel functionality (I read that also some Eigen algorithms profit from enabling omp) and do no further optimizing.\r\n\r\nMini benchmark of concatenation of two ranges (list/vector) with 1000 elements each using splice, insert and copy. For the vectors space is preallocated using reserve.\r\n\r\nBenchmark          |      Time       |    CPU        |Iterations\r\n-----------------------|-----------------|---------------|---------------\r\nBM_ListSplice      |     58 ns       |  58 ns         | 10709471\r\nBM_VectorInsert  |      712 ns    |    712 ns      |  968647\r\nBM_VectorCopy  |      34952 ns |     34952 ns |     19807\r\n\r\nMaybe not surprising.","created_at":"2018-05-22T07:48:37Z","updated_at":"2018-05-22T07:48:37Z","html_url":"https://github.com/nutofem/nuto/pull/257#discussion_r189804755","pull_request_url":"https://api.github.com/repos/nutofem/nuto/pulls/257","author_association":"COLLABORATOR","_links":{"self":{"href":"https://api.github.com/repos/nutofem/nuto/pulls/comments/189804755"},"html":{"href":"https://github.com/nutofem/nuto/pull/257#discussion_r189804755"},"pull_request":{"href":"https://api.github.com/repos/nutofem/nuto/pulls/257"}},"in_reply_to_id":188114062},"pull_request":{"url":"https://api.github.com/repos/nutofem/nuto/pulls/257","id":187799622,"html_url":"https://github.com/nutofem/nuto/pull/257","diff_url":"https://github.com/nutofem/nuto/pull/257.diff","patch_url":"https://github.com/nutofem/nuto/pull/257.patch","issue_url":"https://api.github.com/repos/nutofem/nuto/issues/257","number":257,"state":"open","locked":false,"title":"Add parallel matrix assembly using OpenMp","user":{"login":"pmueller2","id":24247180,"avatar_url":"https://avatars0.githubusercontent.com/u/24247180?v=4","gravatar_id":"","url":"https://api.github.com/users/pmueller2","html_url":"https://github.com/pmueller2","followers_url":"https://api.github.com/users/pmueller2/followers","following_url":"https://api.github.com/users/pmueller2/following{/other_user}","gists_url":"https://api.github.com/users/pmueller2/gists{/gist_id}","starred_url":"https://api.github.com/users/pmueller2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pmueller2/subscriptions","organizations_url":"https://api.github.com/users/pmueller2/orgs","repos_url":"https://api.github.com/users/pmueller2/repos","events_url":"https://api.github.com/users/pmueller2/events{/privacy}","received_events_url":"https://api.github.com/users/pmueller2/received_events","type":"User","site_admin":false},"body":"Adds parallelization of the assembly loops using OpenMp.\r\nCMake option ENABLE_OPENMP (default True) is added to turn it off.\r\nTo change the default number of threads set the environment variable\r\nOMP_NUM_THREADS.","created_at":"2018-05-14T11:40:55Z","updated_at":"2018-05-22T07:48:37Z","closed_at":null,"merged_at":null,"merge_commit_sha":"94acbfd6cf8531d41ce4548fa96aea60d5eac0b3","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/nutofem/nuto/pulls/257/commits","review_comments_url":"https://api.github.com/repos/nutofem/nuto/pulls/257/comments","review_comment_url":"https://api.github.com/repos/nutofem/nuto/pulls/comments{/number}","comments_url":"https://api.github.com/repos/nutofem/nuto/issues/257/comments","statuses_url":"https://api.github.com/repos/nutofem/nuto/statuses/7bd1a22c4ba31021bad7d2802d2d8c8921bf2ffb","head":{"label":"nutofem:PDE_omp_simpleAssembler","ref":"PDE_omp_simpleAssembler","sha":"7bd1a22c4ba31021bad7d2802d2d8c8921bf2ffb","user":{"login":"nutofem","id":20438588,"avatar_url":"https://avatars2.githubusercontent.com/u/20438588?v=4","gravatar_id":"","url":"https://api.github.com/users/nutofem","html_url":"https://github.com/nutofem","followers_url":"https://api.github.com/users/nutofem/followers","following_url":"https://api.github.com/users/nutofem/following{/other_user}","gists_url":"https://api.github.com/users/nutofem/gists{/gist_id}","starred_url":"https://api.github.com/users/nutofem/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nutofem/subscriptions","organizations_url":"https://api.github.com/users/nutofem/orgs","repos_url":"https://api.github.com/users/nutofem/repos","events_url":"https://api.github.com/users/nutofem/events{/privacy}","received_events_url":"https://api.github.com/users/nutofem/received_events","type":"Organization","site_admin":false},"repo":{"id":63241285,"name":"nuto","full_name":"nutofem/nuto","owner":{"login":"nutofem","id":20438588,"avatar_url":"https://avatars2.githubusercontent.com/u/20438588?v=4","gravatar_id":"","url":"https://api.github.com/users/nutofem","html_url":"https://github.com/nutofem","followers_url":"https://api.github.com/users/nutofem/followers","following_url":"https://api.github.com/users/nutofem/following{/other_user}","gists_url":"https://api.github.com/users/nutofem/gists{/gist_id}","starred_url":"https://api.github.com/users/nutofem/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nutofem/subscriptions","organizations_url":"https://api.github.com/users/nutofem/orgs","repos_url":"https://api.github.com/users/nutofem/repos","events_url":"https://api.github.com/users/nutofem/events{/privacy}","received_events_url":"https://api.github.com/users/nutofem/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/nutofem/nuto","description":"NuTo - yet another finite element library","fork":false,"url":"https://api.github.com/repos/nutofem/nuto","forks_url":"https://api.github.com/repos/nutofem/nuto/forks","keys_url":"https://api.github.com/repos/nutofem/nuto/keys{/key_id}","collaborators_url":"https://api.github.com/repos/nutofem/nuto/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/nutofem/nuto/teams","hooks_url":"https://api.github.com/repos/nutofem/nuto/hooks","issue_events_url":"https://api.github.com/repos/nutofem/nuto/issues/events{/number}","events_url":"https://api.github.com/repos/nutofem/nuto/events","assignees_url":"https://api.github.com/repos/nutofem/nuto/assignees{/user}","branches_url":"https://api.github.com/repos/nutofem/nuto/branches{/branch}","tags_url":"https://api.github.com/repos/nutofem/nuto/tags","blobs_url":"https://api.github.com/repos/nutofem/nuto/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/nutofem/nuto/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/nutofem/nuto/git/refs{/sha}","trees_url":"https://api.github.com/repos/nutofem/nuto/git/trees{/sha}","statuses_url":"https://api.github.com/repos/nutofem/nuto/statuses/{sha}","languages_url":"https://api.github.com/repos/nutofem/nuto/languages","stargazers_url":"https://api.github.com/repos/nutofem/nuto/stargazers","contributors_url":"https://api.github.com/repos/nutofem/nuto/contributors","subscribers_url":"https://api.github.com/repos/nutofem/nuto/subscribers","subscription_url":"https://api.github.com/repos/nutofem/nuto/subscription","commits_url":"https://api.github.com/repos/nutofem/nuto/commits{/sha}","git_commits_url":"https://api.github.com/repos/nutofem/nuto/git/commits{/sha}","comments_url":"https://api.github.com/repos/nutofem/nuto/comments{/number}","issue_comment_url":"https://api.github.com/repos/nutofem/nuto/issues/comments{/number}","contents_url":"https://api.github.com/repos/nutofem/nuto/contents/{+path}","compare_url":"https://api.github.com/repos/nutofem/nuto/compare/{base}...{head}","merges_url":"https://api.github.com/repos/nutofem/nuto/merges","archive_url":"https://api.github.com/repos/nutofem/nuto/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/nutofem/nuto/downloads","issues_url":"https://api.github.com/repos/nutofem/nuto/issues{/number}","pulls_url":"https://api.github.com/repos/nutofem/nuto/pulls{/number}","milestones_url":"https://api.github.com/repos/nutofem/nuto/milestones{/number}","notifications_url":"https://api.github.com/repos/nutofem/nuto/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/nutofem/nuto/labels{/name}","releases_url":"https://api.github.com/repos/nutofem/nuto/releases{/id}","deployments_url":"https://api.github.com/repos/nutofem/nuto/deployments","created_at":"2016-07-13T11:42:57Z","updated_at":"2018-05-18T09:35:47Z","pushed_at":"2018-05-22T07:27:08Z","git_url":"git://github.com/nutofem/nuto.git","ssh_url":"git@github.com:nutofem/nuto.git","clone_url":"https://github.com/nutofem/nuto.git","svn_url":"https://github.com/nutofem/nuto","homepage":"https://nuto.readthedocs.io","size":18607,"stargazers_count":8,"watchers_count":8,"language":"C++","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":2,"mirror_url":null,"archived":false,"open_issues_count":45,"license":{"key":"bsl-1.0","name":"Boost Software License 1.0","spdx_id":"BSL-1.0","url":"https://api.github.com/licenses/bsl-1.0"},"forks":2,"open_issues":45,"watchers":8,"default_branch":"develop"}},"base":{"label":"nutofem:develop","ref":"develop","sha":"9fe4b890de7264b0c551d2cc03d97df8b7c23763","user":{"login":"nutofem","id":20438588,"avatar_url":"https://avatars2.githubusercontent.com/u/20438588?v=4","gravatar_id":"","url":"https://api.github.com/users/nutofem","html_url":"https://github.com/nutofem","followers_url":"https://api.github.com/users/nutofem/followers","following_url":"https://api.github.com/users/nutofem/following{/other_user}","gists_url":"https://api.github.com/users/nutofem/gists{/gist_id}","starred_url":"https://api.github.com/users/nutofem/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nutofem/subscriptions","organizations_url":"https://api.github.com/users/nutofem/orgs","repos_url":"https://api.github.com/users/nutofem/repos","events_url":"https://api.github.com/users/nutofem/events{/privacy}","received_events_url":"https://api.github.com/users/nutofem/received_events","type":"Organization","site_admin":false},"repo":{"id":63241285,"name":"nuto","full_name":"nutofem/nuto","owner":{"login":"nutofem","id":20438588,"avatar_url":"https://avatars2.githubusercontent.com/u/20438588?v=4","gravatar_id":"","url":"https://api.github.com/users/nutofem","html_url":"https://github.com/nutofem","followers_url":"https://api.github.com/users/nutofem/followers","following_url":"https://api.github.com/users/nutofem/following{/other_user}","gists_url":"https://api.github.com/users/nutofem/gists{/gist_id}","starred_url":"https://api.github.com/users/nutofem/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nutofem/subscriptions","organizations_url":"https://api.github.com/users/nutofem/orgs","repos_url":"https://api.github.com/users/nutofem/repos","events_url":"https://api.github.com/users/nutofem/events{/privacy}","received_events_url":"https://api.github.com/users/nutofem/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/nutofem/nuto","description":"NuTo - yet another finite element library","fork":false,"url":"https://api.github.com/repos/nutofem/nuto","forks_url":"https://api.github.com/repos/nutofem/nuto/forks","keys_url":"https://api.github.com/repos/nutofem/nuto/keys{/key_id}","collaborators_url":"https://api.github.com/repos/nutofem/nuto/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/nutofem/nuto/teams","hooks_url":"https://api.github.com/repos/nutofem/nuto/hooks","issue_events_url":"https://api.github.com/repos/nutofem/nuto/issues/events{/number}","events_url":"https://api.github.com/repos/nutofem/nuto/events","assignees_url":"https://api.github.com/repos/nutofem/nuto/assignees{/user}","branches_url":"https://api.github.com/repos/nutofem/nuto/branches{/branch}","tags_url":"https://api.github.com/repos/nutofem/nuto/tags","blobs_url":"https://api.github.com/repos/nutofem/nuto/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/nutofem/nuto/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/nutofem/nuto/git/refs{/sha}","trees_url":"https://api.github.com/repos/nutofem/nuto/git/trees{/sha}","statuses_url":"https://api.github.com/repos/nutofem/nuto/statuses/{sha}","languages_url":"https://api.github.com/repos/nutofem/nuto/languages","stargazers_url":"https://api.github.com/repos/nutofem/nuto/stargazers","contributors_url":"https://api.github.com/repos/nutofem/nuto/contributors","subscribers_url":"https://api.github.com/repos/nutofem/nuto/subscribers","subscription_url":"https://api.github.com/repos/nutofem/nuto/subscription","commits_url":"https://api.github.com/repos/nutofem/nuto/commits{/sha}","git_commits_url":"https://api.github.com/repos/nutofem/nuto/git/commits{/sha}","comments_url":"https://api.github.com/repos/nutofem/nuto/comments{/number}","issue_comment_url":"https://api.github.com/repos/nutofem/nuto/issues/comments{/number}","contents_url":"https://api.github.com/repos/nutofem/nuto/contents/{+path}","compare_url":"https://api.github.com/repos/nutofem/nuto/compare/{base}...{head}","merges_url":"https://api.github.com/repos/nutofem/nuto/merges","archive_url":"https://api.github.com/repos/nutofem/nuto/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/nutofem/nuto/downloads","issues_url":"https://api.github.com/repos/nutofem/nuto/issues{/number}","pulls_url":"https://api.github.com/repos/nutofem/nuto/pulls{/number}","milestones_url":"https://api.github.com/repos/nutofem/nuto/milestones{/number}","notifications_url":"https://api.github.com/repos/nutofem/nuto/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/nutofem/nuto/labels{/name}","releases_url":"https://api.github.com/repos/nutofem/nuto/releases{/id}","deployments_url":"https://api.github.com/repos/nutofem/nuto/deployments","created_at":"2016-07-13T11:42:57Z","updated_at":"2018-05-18T09:35:47Z","pushed_at":"2018-05-22T07:27:08Z","git_url":"git://github.com/nutofem/nuto.git","ssh_url":"git@github.com:nutofem/nuto.git","clone_url":"https://github.com/nutofem/nuto.git","svn_url":"https://github.com/nutofem/nuto","homepage":"https://nuto.readthedocs.io","size":18607,"stargazers_count":8,"watchers_count":8,"language":"C++","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":2,"mirror_url":null,"archived":false,"open_issues_count":45,"license":{"key":"bsl-1.0","name":"Boost Software License 1.0","spdx_id":"BSL-1.0","url":"https://api.github.com/licenses/bsl-1.0"},"forks":2,"open_issues":45,"watchers":8,"default_branch":"develop"}},"_links":{"self":{"href":"https://api.github.com/repos/nutofem/nuto/pulls/257"},"html":{"href":"https://github.com/nutofem/nuto/pull/257"},"issue":{"href":"https://api.github.com/repos/nutofem/nuto/issues/257"},"comments":{"href":"https://api.github.com/repos/nutofem/nuto/issues/257/comments"},"review_comments":{"href":"https://api.github.com/repos/nutofem/nuto/pulls/257/comments"},"review_comment":{"href":"https://api.github.com/repos/nutofem/nuto/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/nutofem/nuto/pulls/257/commits"},"statuses":{"href":"https://api.github.com/repos/nutofem/nuto/statuses/7bd1a22c4ba31021bad7d2802d2d8c8921bf2ffb"}},"author_association":"COLLABORATOR"}}
{"actor":{"display_login":"pmueller2"}}