1 #include <../../nrnconf.h>
73 void (*nrnmpi_splitcell_compute_)();
100 double debugsolve(
void)
111 for (inode =
sec->nnode - 1; inode >= 0; inode--) {
112 nd =
sec->pnode[inode];
113 nd->savd =
NODED(nd);
124 for (inode =
sec->nnode - 1; inode >= 0; inode--) {
125 ndP =
sec->pnode + inode;
126 nd =
sec->pnode[inode];
135 if (inode < sec->nnode - 1) {
162 ratio = ((double) inode + .5) / ((double)
sec->nnode - 1.);
184 while (sec1 != sec2) {
204 if (node1 != node2) {
209 }
else if (node1 != node2) {
227 double d, d_origin{};
231 static Node* origin_node;
232 Node* my_origin_node;
242 mode = (int)
chkarg(1, 0., 1.);
248 (*nrnpy_o2loc2_p_)(o, &my_origin_sec, &d_origin);
250 if (!my_origin_sec) {
252 "If first argument is an Object, it needs to be a Python Segment "
253 "object, a rxd.node object, or something with a segment property.");
255 my_origin_node =
node_exact(my_origin_sec, d_origin);
257 }
else if (
ifarg(1)) {
272 "Need to initialize origin with distance()");
276 my_origin_node = origin_node;
305 for (
i = 0;
i < offset;
i++)
308 for (
i = 2;
i <
sec->nnode;
i++)
310 if (
sec->prop->dparam[4].get<
double>() == 1) {
313 Printf(
"| %s%s with %g rall branches\n",
316 sec->prop->dparam[4].get<
double>());
321 for (scnt = 0, ch =
sec->child; ch; ++scnt, ch = ch->
sibling) {
328 dashes(ch,
i + offset + 1, 0140);
335 printf(
"\nnrn_solve enter %lx\n", (
long)_nt);
341 (*nrn_multisplit_solve_)();
352 Fprintf(stderr,
"solve error = %g\n", err);
378 if (nrnmpi_splitcell_compute_) {
380 (*nrnmpi_splitcell_compute_)();
387 printf(
"\nnrn_solve leave %lx\n", (
long)_nt);
401 for (
i = i3 - 1;
i >= i2; --
i) {
412 auto const i2 = i1 + _nt->
ncell;
413 auto const i3 = _nt->
end;
417 for (
int i = i1;
i < i2; ++
i) {
420 for (
int i = i2;
i < i3; ++
i) {
428 sec->volatile_mark = 0;
432 return sec->volatile_mark++;
435 return sec->volatile_mark;
457 if (
sec->nnode == 0) {
477 if (
auto* ob =
sec->prop->dparam[6].get<
Object*>();
478 ob && ob->
secelm_ == secitem) {
489 if (!
sec->parentsec &&
sec->parentnode) {
490 delete std::exchange(
sec->parentnode,
nullptr);
494 free((
char*)
sec->pt3d);
499 if (
sec->logical_connection) {
500 free(
sec->logical_connection);
501 sec->logical_connection = (
Pt3d*) 0;
511 if (--
sec->refcount <= 0) {
513 printf(
"section_unref: freed\n");
542 for (child =
sec->child; child; child = child->
sibling) {
556 for (Eqnblock* e = eqnblock; e;) {
557 free(std::exchange(e, e->eqnblock_next));
570 for (
int i =
n - 1;
i >= 0; --
i) {
571 delete std::exchange(
pnode[
i],
nullptr);
573 delete[] std::exchange(
pnode,
nullptr);
594 for (
j = 0;
j < jmax; ++
j) {
597 py = p1->ob->u.dataspace[ps->
u.
rng.index].pval;
599 for (std::size_t
i = 0;
i < imax; ++
i) {
604 for (
int i = 0;
i < p1->param_num_vars(); ++
i) {
605 for (
auto j = 0;
j < p1->param_array_dimension(
i); ++
j) {
617 while (p2 && p2->
_type != p1->_type) {
621 p2->
dparam[0] = p1->dparam[0].
get<
int>();
634 pn2 =
new Node* [nseg] {};
647 for (i1 = 0; i1 < n1; ++i1) {
648 x = (i1 + .5) / (
double) n1;
653 for (i2 = 0; i2 < n2; ++i2)
654 if (pn2[i2] ==
NULL) {
655 x = (i2 + 0.5) / (
double) n2;
659 for (i1 = 0; i1 < n1; ++i1) {
663 for (i2 = 0; i2 < n2; ++i2) {
664 x = (i2 + .5) / (
double) n2;
671 for (i2 = 0; i2 < n2; ++i2) {
673 x2 = (i2 + 1.) / (
double) n2;
674 for (; i1 < n1; ++i1) {
675 x1 = (i1 + .5) / (
double) n1;
679 if (pn1[i1] == (
Node*) 0) {
683 printf(
"moving point processes from pn1[%d] to pn2[%d]\n", i1, i2);
684 printf(
"i.e. x1=%g in the range %g to %g\n", x1, x2-1./n2, x2);
692 for (i2 = 0; i2 < nseg; ++i2) {
696 if (
sec->pnode[
sec->nnode - 1]->extnode) {
717 sec->pnode =
new Node* [nseg] {};
719 for (
i = 0;
i < nseg; ++
i) {
721 sec->pnode[
i]->sec_node_index_ =
i;
724 for (
i = 0;
i < nseg; ++
i) {
751 if (!
sec->parentsec) {
762 for (psec =
sec->parentsec; psec;
s = psec, psec = psec->
parentsec) {
763 if (!psec ||
s->order >= 0) {
765 }
else if (psec ==
sec) {
766 fprintf(stderr,
"A loop exists consisting of:\n %s",
secname(
sec));
767 for (
s =
sec->parentsec;
s !=
sec;
s =
s->parentsec) {
771 " %s\nUse <section> disconnect() to break the loop\n ",
double nrn_section_orientation(Section *sec)
const char * secname(Section *sec)
name of section (for use in error messages)
int node_index_exact(Section *sec, double x)
return -1 if x at connection end, nnode-1 if at other end
void setup_topology(void)
double section_length(Section *sec)
double nrn_connection_position(Section *sec)
void nrn_disconnect(Section *sec)
Node * node_exact(Section *sec, double x)
like node_index but give proper node when x is 0 or 1 as well as in between
static double order(void *v)
Section * nrn_section_alloc()
void nrn_section_free(Section *s)
void extcell_2d_alloc(Section *sec)
void extnode_free_elements(Extnode *nde)
double chkarg(int, double low, double high)
void nrn_print_matrix(NrnThread *_nt)
size_t hoc_total_array_data(const Symbol *s, Objectdata *obd)
void hoc_pushobj(Object **d)
int hoc_is_double_arg(int narg)
void hoc_retpushx(double x)
void hoc_l_delete(hoc_Item *)
constexpr auto range_sec(hoc_List *iterable)
Object ** hoc_objgetarg(int)
void notify_freed_val_array(double *p, size_t size)
void hoc_execerror(const char *s1, const char *s2)
static void * emalloc(size_t size)
int Sprintf(char(&buf)[N], const char *fmt, Args &&... args)
Redirect sprintf to snprintf if the buffer size can be deduced.
Prop * prop_alloc(Prop **, int, Node *)
void nrn_seg_or_x_arg2(int iarg, Section **psec, double *px)
void nrn_relocate_old_points(Section *oldsec, Node *oldnode, Section *sec, Node *node)
static Node * node(Object *)
int const size_t const size_t n
std::vector< Memb_func > memb_func
void nrn_thread_error(const char *s)
void nrn_clear_mark(void)
static Section * origin_sec
void(* nrnpy_o2loc2_p_)(Object *, Section **, double *)
void nrn_sec_ref(Section **psec, Section *sec)
void sec_free(hoc_Item *secitem)
short nrn_value_mark(Section *sec)
void(* nrn_multisplit_solve_)()
static void node_realloc(Section *sec, short nseg)
double node_dist(Section *sec, Node *node)
void nrnhoc_topology(void)
void(* nrnpy_o2loc_p_)(Object *, Section **, double *)
static Node * node_clone(Node *nd1)
void section_unref(Section *sec)
double topol_distance(Section *sec1, Node *node1, Section *sec2, Node *node2, Section **prootsec, Node **prootnode)
short nrn_increment_mark(Section *sec)
static void triang(NrnThread *)
void node_destruct(Node **pnode, int n)
void nrn_solve(NrnThread *_nt)
Section * sec_alloc()
Allocate a new Section object.
void node_alloc(Section *sec, short nseg)
void section_ref(Section *sec)
static void section_unlink(Section *sec)
static void dashes(Section *sec, int offset, int first)
static void bksub(NrnThread *)
Object ** hoc_objpop()
Pop pointer to object pointer and return top elem from stack.
static void pnode(Prop *)
int spFactor(char *eMatrix)
void spSolve(char *eMatrix, spREAL *RHS, spREAL *Solution, std::optional< spREAL * > iRHS=std::nullopt, std::optional< spREAL * > iSolution=std::nullopt)
Represent main neuron object computed by single thread.
double * node_a_storage()
double * node_rhs_storage()
double * node_d_storage()
double * node_b_storage()
double & param(int field_index, int array_index=0)
Return a reference to the i-th floating point data field associated with this Prop.
struct Symbol::@45::@46 rng
T get() const
Explicit conversion to any T.
void update_actual_d_based_on_sp13_mat(NrnThread *nt)
void update_actual_rhs_based_on_sp13_rhs(NrnThread *nt)
void update_sp13_rhs_based_on_actual_rhs(NrnThread *nt)
void update_sp13_mat_based_on_actual_d(NrnThread *nt)
int Fprintf(FILE *stream, const char *fmt, Args... args)
int Printf(const char *fmt, Args... args)