61 #include <cuda_runtime.h>
63 #if defined HAS_ROCM_MODEL && defined __HIP__
64 #include <hip/hip_runtime.h>
68 #include "petsc_utils.h"
72 using ::opencarp::base_timer;
83 using ::opencarp::Salt_list;
88 #ifdef USE_FMEM_WRAPPER
107 static MULTI_IF *gMIIF_Error_Recovery;
108 static int current_IIF_index;
109 static float current_time = 0;
110 static float start_time = 0;
112 static void prepare_error_recovery(
MULTI_IF *MIIF,
int IIF_index,
float time) {
113 gMIIF_Error_Recovery = MIIF;
114 current_IIF_index = IIF_index;
115 current_time = start_time+time;
119 return gMIIF_Error_Recovery->
NodeLists[current_IIF_index][local_node];
126 static int g_print_bounds_exceeded = 1;
129 return g_print_bounds_exceeded;
133 int oldval = g_print_bounds_exceeded;
135 g_print_bounds_exceeded = newval;
158 int ***NodeLists,
int numNode)
164 int *NodeNum =
static_cast<int *
>(calloc(N_IIF,
sizeof(
int)));
165 int **NodeLst =
static_cast<int **
>(calloc(N_IIF,
sizeof(
int *)));
168 for (
int i = 0; i < numNode; i++)
169 NodeNum[
static_cast<int>(IIF_Mask[i])]++;
174 for (
int i = 0; i < N_IIF; i++) {
176 NodeLst[i] =
static_cast<int *
>(malloc(
sizeof(
int *) * NodeNum[i]));
182 for (
int j = 0; j < N_IIF; j++) {
184 for (
int i = 0; i < numNode; i++)
185 if (IIF_Mask[i] == j)
186 NodeLst[j][hcount++] = i;
189 for(
int j=0; j<N_IIF; j++)
190 std::sort(NodeLst[j], NodeLst[j]+NodeNum[j]);
193 *NodeLists = NodeLst;
222 int N_IIF = pMIIF->
N_IIF;
224 pMIIF->
contiguous =
static_cast<bool *
>(calloc(N_IIF,
sizeof(
bool)));
229 for (std::size_t i = 0; i < pMIIF->
N_IIF; i++) {
230 pMIIF->
ldata[i] = allocate_on_target<GlobalData_t*>(pMIIF->
iontypes[i].get().select_target(pMIIF->
targets[i]), NUM_IMP_DATA_TYPES);
234 for (
int i = 0; i < pMIIF->
N_IIF; i++) {
253 for (
auto& imp : pMIIF->
IIF) {
254 imp->initialize_params();
263 for (
int i = 0; i < pMIIF->
IIF.size(); i++)
264 pMIIF->
IIF[i]->initialize(pMIIF->
dt, pMIIF->
ldata[i]);
278 unsigned int *moddat =
static_cast<unsigned int *
>(calloc(this->
N_IIF,
sizeof(
unsigned int)));
280 for (
int i = 0; i < this->
N_IIF; i++) {
281 moddat[i] = this->
IIF[i]->get_moddat();
282 this->
IIF[i]->set_moddat(moddat[i] | this->
IIF[i]->get_reqdat());
285 for (
int i = 0; i < this->
N_IIF; i++) {
286 this->
IIF[i]->set_moddat(moddat[i]);
306 #define FILENAME_BUF 1024
310 return *(
int *)a - *(
int *)b;
342 if (!n_traceNodes)
return;
344 if (n_traceNodes > 1000)
345 log_msg(0, 4, 0,
"%s warning: %d trace nodes may impact performance", __func__, n_traceNodes);
355 for (
int iTrace = 0; iTrace < n_traceNodes; iTrace++) {
356 mesh_int_t lnode = imesh ? imesh->
pl.localize(traceNodes[iTrace]) : traceNodes[iTrace];
361 if(petsc2nod.
in_b(lnode) ==
false)
continue;
367 for (
int iRegion = 0; iRegion < MIIF->
N_IIF; iRegion++)
369 auto target =
static_cast<int *
>(bsearch(&lnode, MIIF->
NodeLists[iRegion],
372 if (target != NULL ) {
373 int idx = target - MIIF->
NodeLists[iRegion];
375 trace_info->
found =
true;
376 trace_info->
region = iRegion;
382 for (
int iTrace = 0; iTrace < n_traceNodes; iTrace++) {
385 log_msg(0,4,0,
"trace node %d not found", traceNodes[iTrace]);
390 snprintf(traceName,
sizeof traceName,
"Trace_%d.dat", label ? label[iTrace] : traceNodes[iTrace]);
415 #define MAX_TRACE_LINE_LEN 8196
419 std::vector<IonIfBase*>& IIF = MIIF->
IIF;
430 fprintf(fs,
"%4.10f\t", time);
431 if (IIF[ctrace->
region]->get_type().has_trace()) {
435 for (
auto& plugin : IIF[ctrace->
region]->plugins()) {
436 if (plugin->get_type().has_trace()) {
438 plugin->get_type().trace(
446 fprintf(ctrace->
file->
fd,
"%s", trace_buf);
488 std::vector<IonIfBase*>& pIF = this->
IIF;
489 for (
auto& IF : pIF) {
490 int ndmps = IF->dump_luts(zipped);
491 if (ndmps < IF->tables().size()) {
492 log_msg(
logger, 4, 0,
"LUT dump error %s: only %d out of %d LUTs dumped.\n",
493 IF->get_type().get_name().c_str(), ndmps, IF->tables().size());
495 for (
auto& plugin : IF->plugins()) {
496 ndmps = plugin->dump_luts(zipped);
497 if (ndmps < plugin->tables().size()) {
498 log_msg(
logger, 4, 0,
"LUT dump error %s: only %d out of %d LUTs dumped.\n",
499 plugin->get_type().get_name().c_str(), ndmps, IF->tables().size());
513 for (
int i = 0; i <
svd.
n; i++)
530 char *
get_sv(
void *tab,
int offset,
int n,
int svSize,
int size) {
531 char *buf =
static_cast<char *
>(malloc(n*size));
533 char *p =
static_cast<char *
>(tab) + offset;
535 for (
int i = 0; i < n; i++) {
553 if (iot->triggered) {
554 for (
int i = 0; i <
svd.
n; i++) {
559 nwr += SF::root_write<char>(fd, (
char*) buf,
svd.
size[i]*
svd.
num[i], PETSC_COMM_WORLD);
576 void update_vm(
int start,
int end,
double *vm,
double *ion,
double dt)
578 int i = blockIdx.x*blockDim.x + threadIdx.x;
580 vm[i] = vm[i] + (ion[i] * (-dt));
588 if (flag_send == 1) {
592 for (
int j = 0; j < this->
numSubDt; j++)
594 for (
int i = 0; i < this->
N_IIF; i++)
597 if (!this->
N_Nodes[i])
continue;
599 prepare_error_recovery(
this, i, pIF->
get_tstp().
cnt * this->dt);
611 fprintf(stderr,
"LIMPET compute fail in %s at node %d (local %d)! Aborting!\n",
612 this->
name.c_str(), this->NodeLists[i][j], j);
617 }
while (current < this->
N_Nodes[i]);
619 for (
auto& plugin : pIF->
plugins()) {
625 plugin->compute(current, this->
N_Nodes[i], this->
ldata[i]);
628 if (plugin ==
nullptr)
634 fprintf(stderr,
"LIMPET plugin fail in %s at node %d (local %d)! Aborting!\n",
635 this->
name.c_str(), this->NodeLists[i][j], j);
640 }
while (current < this->
N_Nodes[i]);
649 #if defined __CUDA__ || defined __HIP__
652 cudaDeviceSynchronize();
653 #elif defined __HIP__
654 hipDeviceSynchronize();
657 fprintf(stderr,
"GPU/CUDA not found");
662 if (flag_receive == 1) {
677 for (
auto& pIF : this->
IIF) {
678 pIF->get_type().destroy_ion_if(pIF);
689 for (
int i = 0; i < pMIIF->
N_IIF; i++) {
697 for (
int j = 0; j < NUM_IMP_DATA_TYPES; j++) {
705 allocate_on_target<GlobalData_t>(pMIIF->
IIF[i]->get_target(),
708 if (pMIIF->
gdata[j] == NULL) {
709 log_msg(pMIIF->
logger, 5,
LOCAL,
"IMP data type %s not supplied for region %d", imp_data_names[j], i);
727 for (
int j = 0; j < NUM_IMP_DATA_TYPES; j++) {
729 if (this->
gdata[j] != NULL) {
737 for (
int i = 0; i < this->
N_IIF; i++) {
745 for (
int k = 0; k < this->
N_Nodes[i]; k++)
746 this->
ldata[i][j][k] = rdata[ip[k]];
762 for (
int i = 0; i < this->
N_IIF; i++) {
763 if (!this->
N_Nodes[i])
continue;
766 if (
is_gpu(this->
IIF[i]->get_target())) {
767 for (
int j = 0; j < NUM_IMP_DATA_TYPES; j++) {
773 for (
int k = 0; k < this->
N_Nodes[i]; k++)
779 for (
int j = 0; j < NUM_IMP_DATA_TYPES; j++) {
780 if (this->
IIF[i]->get_moddat() & imp_data_flag[j]) {
782 for (
int k = 0; k < this->
N_Nodes[i]; k++)
790 for (
int j = 0; j < NUM_IMP_DATA_TYPES; j++)
791 if (this->
gdata[j] != NULL)
797 for (
int j = 0; j < NUM_IMP_DATA_TYPES; j++) {
798 if (pMIIF->
gdata[j] != NULL) {
799 for (
int i = 0; i < pMIIF->
N_IIF; i++)
801 deallocate_on_target<GlobalData_t>(pMIIF->
IIF[i]->get_target(),
804 delete pMIIF->
gdata[j];
821 if (plgstr == NULL) {
822 *out_num_plugins = 0;
828 char *plugspec =
dupstr(plgstr);
830 char *token =
tokstr_r(plugspec,
":", &saveptr);
832 *out_num_plugins = 0;
839 out_plugins.push_back(*type);
841 token =
tokstr_r(NULL,
":", &saveptr);
844 *out_num_plugins = out_plugins.size();
875 if (index(variable,
'.') == NULL) {
879 for (
int ii = 0; ii < NUM_IMP_DATA_TYPES; ii++) {
880 if (strcmp(variable, imp_data_names[ii]) == 0) {
886 log_msg(
logger, 5,
FLUSH,
"Error! No external variable named %s in this build of openCARP.", variable);
891 if (this->
gdata[data_id] == NULL) {
893 "External variable %s is not being used this processor.\n"
894 "Is this really what you meant to do?\n"
895 "Perhaps you don't have the correct Ionic models selected.",
896 imp_data_names[data_id]);
902 for (
size_t i = 0; i < indices.
size(); i++) {
903 raw_data[indices[i]] = values[i];
914 char *my_variable =
dupstr(variable);
915 char *IIF_name =
tokstr_r(my_variable,
".", &saveptr);
916 char *sv_name =
tokstr_r(NULL,
".", &saveptr);
920 log_msg(
logger, 5, 0,
"%s error: %s is not a valid IMP name.", __func__, IIF_name);
927 if (sv_get == NULL) {
928 log_msg(
logger, 5, 0,
"%s error: %s is not a valid state variable for the %s model.",
929 __func__, sv_name, IIF_name);
935 for (
int i_iif = 0; i_iif < this->
N_IIF; i_iif++) {
937 if (this->
IIF[i_iif]->get_type() == *type) {
938 lIIF = this->
IIF[i_iif];
942 for (
auto& plugin : this->
IIF[i_iif]->plugins()) {
943 if (plugin->get_type() == *type) {
954 for (
size_t ii = 0; ii < indices.
size(); ii++) {
957 int *target =
static_cast<int*
>(bsearch(&indices[ii], this->
NodeLists[i_iif],
962 sv_put(*lIIF, (
int)(target - this->
NodeLists[i_iif]), sv_offset, file_value);
970 MPI_Allreduce(MPI_IN_PLACE, &num_changed, 1, MPI_INT, MPI_SUM, PETSC_COMM_WORLD);
999 long loff = offset[0];
1000 for (
int i = 0; i < N; i++)
1001 if (offset[i]-loff > bufsize) {
1008 *ranges = (
int *)r.data;
1011 MPI_Bcast(&nitems, 1, MPI_INT, 0, PETSC_COMM_WORLD);
1013 *ranges =
static_cast<int *
>(malloc( (nitems+1)*
sizeof(
int) ));
1014 MPI_Bcast(*ranges, nitems+1, MPI_INT, 0, PETSC_COMM_WORLD);
1057 bool append,
unsigned int revision)
1067 log_msg(
logger, 0, 0,
"Saving state at time %f in file: %s", simtime, fname);
1070 out =
f_open(fname, append ?
"a" :
"w");
1073 fseek(out->fd, 0, SEEK_END);
1076 fwrite(&MIIF_Format,
sizeof(
unsigned int), 1, out->fd);
1077 fwrite(&revision,
sizeof(
unsigned int), 1, out->fd);
1078 time_t tm = time(NULL);
1079 fwrite(&tm,
sizeof(time_t), 1, out->fd);
1080 fwrite(&simtime,
sizeof(
float), 1, out->fd);
1081 fwrite(&miif_node_gsize,
sizeof(
int), 1, out->fd);
1084 for (
int i = 0; i < NUM_IMP_DATA_TYPES; i++)
1085 if (this->
gdata[i]) num_gdata++;
1087 fwrite(&num_gdata,
sizeof(
int), 1, out->fd);
1098 FILE* fd = rank == 0 ? out->fd : NULL;
1101 for (
int i = 0; i < NUM_IMP_DATA_TYPES; i++) {
1102 if (this->
gdata[i]) {
1106 log_msg(NULL, 0, 0,
"\tDumping %s at %d", imp_data_names[i], ftell(fd) );
1119 outVec->write_binary<
SF_real>(fd);
1131 int* imp_mem =
new int[this->
N_IIF];
1132 size_t *offset = NULL;
1137 log_msg(NULL, 0, 0,
"\tDumping IMP sizes at %d", ftell(fd) );
1141 fwrite(&this->
N_IIF,
sizeof(
int), 1, fd);
1143 for (
int i = 0; i < this->
N_IIF; i++) {
1148 fwrite(&sv_size,
sizeof(
int), 1, fd);
1149 unsigned long n_plugins = (
unsigned long) imp->
plugins().size();
1150 fwrite(&n_plugins,
sizeof(
int), 1, fd);
1153 for (
auto& plug : imp->
plugins()) {
1156 fwrite(&sv_size,
sizeof(
int), 1, fd);
1157 imp_mem[i] += plug->get_sv_size();
1160 filepos = ftell(fd);
1163 MPI_Bcast(imp_mem, this->
N_IIF, MPI_INT, 0, PETSC_COMM_WORLD);
1176 for(
size_t i=0; i<alg_idx.
size(); i++) loc2canon[i] = canon_nbr[alg_idx[i]];
1184 for (
int i = 0; i < this->
numNode; i++) loc2canon[i] = layout[rank] + i;
1188 int *canord =
new int[this->
numNode];
1189 for (
int i = 0; i < this->
numNode; i++)
1190 canord[i] = loc2canon[i];
1193 log_msg(NULL, 0, 0,
"\tDumping IMP masks at %d", filepos);
1196 SF::root_write_ordered<int, IIF_Mask_t>(fd, canord,
IIFmask,
numNode, PETSC_COMM_WORLD);
1202 impsize[i] = imp_mem[(
int)
IIFmask[i]];
1206 size_t num_entr =
SF::sum(impsize);
1210 for (
int imp_idx = 0; imp_idx < this->
N_IIF; imp_idx++)
1216 for (
int imp_nod_idx = 0; imp_nod_idx < this->
N_Nodes[imp_idx]; imp_nod_idx+=vec_size) {
1217 int index = imp_nod_idx / vec_size;
1218 int loc = this->
NodeLists[imp_idx][imp_nod_idx];
1221 char* write = impdata.
data() + impdsp[loc];
1223 memcpy(write, read, svSize);
1226 for (
auto& plug : iif->
plugins()) {
1227 int plugsize = plug->get_sv_size();
1229 write = impdata.
data() + impdsp[loc] + shift;
1230 read = (
char*) plug->get_sv_address() + index * plugsize;
1231 memcpy(write, read, plugsize);
1238 SF::root_write_ordered<int, char>(fd, canord, impsize.data(), impdata.
data(),
1239 numNode, num_entr, PETSC_COMM_WORLD);
1245 double dump_time =
timing(t1, t0);
1274 static char *last_fn = NULL;
1283 if (fname) in =
f_open(fname,
"r");
1286 if (fname)
log_msg(
logger, 5, 0,
"Error: cannot open file: %s\n", fname);
1287 else log_msg(
logger, 5, 0,
"Error: file stream not open yet");
1292 log_msg(
logger, 5, 0,
"%s is not a recognized MIIF dump file", fname);
1303 last_fn = strdup(fname);
1309 unsigned int format, version;
1312 f_read_par(&format,
sizeof(
unsigned int), 1, in);
1313 f_read_par(&version,
sizeof(
unsigned int), 1, in);
1314 f_read_par(&save_date,
sizeof(time_t), 1, in);
1316 log_msg(
logger, 0, 0,
"Restoring time %f from %s (format v%d) generated\n\tby calling "
1317 "program r%d on %s", time, fname, format, version, ctime(&save_date) );
1319 int savedNum, glob_numNode;
1320 MPI_Allreduce(&this->
numNode, &glob_numNode, 1, MPI_INT, MPI_SUM, PETSC_COMM_WORLD);
1323 if (savedNum != glob_numNode) {
1324 log_msg(
logger, 5, 0,
"expecting %d nodes but read %d nodes", glob_numNode, savedNum);
1332 for (
int g = 0; g < num_gdata; g++) {
1335 for (i = 0; i < NUM_IMP_DATA_TYPES; i++) {
1336 if (!strcmp(datatype, imp_data_names[i]) ) {
1337 if (this->
gdata[i]) {
1338 log_msg(
logger, 0, 0,
"\tRestoring global data %s", imp_data_names[i], datatype);
1340 FILE* fd = my_rank == 0 ? in->fd : NULL;
1343 petsc2canon(*this->
gdata[i], fwd);
1345 log_msg(
logger, 0, 0,
"\tGlobal data %s not used", datatype);
1350 if (i == NUM_IMP_DATA_TYPES)
1351 log_msg(
logger, 3, 0,
"\tSaved global data %s not recognized", datatype);
1353 if ( (my_rank == 0) && ((i == NUM_IMP_DATA_TYPES) || !this->
gdata[i]) )
1354 fseek(in->fd, this->gdata[i]->gsize() *
sizeof(
SF_real), SEEK_CUR);
1364 int *IMPsz =
static_cast<int *
>(malloc(
N_IIF *
sizeof(
int)));
1366 for (
int i = 0; i <
N_IIF; i++) {
1369 f_read_par(&imps[i].nplug,
sizeof(
int), 1, in);
1372 IMPsz[i] = imps[i].
sz;
1375 for (
int j = 0; j < imps[i].
nplug; j++) {
1378 f_read_par(&imps[i].plug[j].sz,
sizeof(
int), 1, in);
1379 IMPsz[i] += imps[i].
plug[j].
sz;
1384 for (
int i = 0; i <
N_IIF; i++) {
1385 if (i >= this->N_IIF) {
1386 log_msg(NULL, 3, 0,
"Saved IMP region %d out of range", i);
1389 if (strcmp(imps[i].
name, this->
IIF[i]->get_type().get_name().c_str()) ) {
1390 log_msg(NULL, 3, 0,
"Saved IMP region %d ionic model does not match that of IMP region %d", i, i);
1393 if (imps[i].sz != this->
IIF[i]->get_sv_size()) {
1394 log_msg(NULL, 3, 0,
"Saved IMP region %d size does not match current IMP size", i);
1400 for (
int j = 0; j < imps[i].
nplug; j++)
1401 for (
int k = 0; k < this->
IIF[i]->plugins().size(); k++)
1402 if (!strcmp(imps[i].plug[j].
name, this->
IIF[i]->plugins()[k]->get_type().get_name().c_str()) &&
1403 (imps[i].plug[j].sz == this->
IIF[i]->plugins()[k]->get_sv_size()) ) {
1404 log_msg(NULL, 3, 0,
"Saved IMP region %d plugin %s compatible", i, imps[i].plug[j].
name);
1413 IIF_Mask_t *canMask =
static_cast<char *
>(malloc(glob_numNode*
sizeof(this->
IIFmask[0]) ));
1417 size_t *offset =
static_cast<size_t *
>(calloc(glob_numNode+1,
sizeof(
size_t)));
1418 for (
int i = 1; i <= glob_numNode; i++)
1419 offset[i] = offset[i-1] + IMPsz[
static_cast<int>(canMask[i-1])];
1427 SVstart = ftell(in->fd);
1431 MPI_Bcast(&SVstart,
sizeof(
long), MPI_BYTE, 0, PETSC_COMM_WORLD);
1440 for(
size_t i=0; i<alg_idx.
size(); i++) loc2canon[i] = canon_nbr[alg_idx[i]];
1443 for (
int pid = 0; pid < mpi_size; pid++) {
1444 if (my_rank == pid) {
1448 for (
int i = 0; i <
N_IIF; i++) {
1449 fseek(in->fd, SVstart, SEEK_SET);
1451 canMask, offset, imps+i, loc2canon.
data());
1456 MPI_Barrier(PETSC_COMM_WORLD);
1461 MPI_Reduce(my_rank ? &mismatch : MPI_IN_PLACE, &mismatch, 1, MPI_INT, MPI_SUM, 0, PETSC_COMM_WORLD);
1462 if ( (my_rank == 0) && mismatch)
1463 log_msg(NULL, 3, 0,
"Number of nonmatching nodes: %d", mismatch);
1465 if ( (my_rank == 0) && (!close) ) {
1470 fseek(in->fd, SVstart+offset[glob_numNode], SEEK_SET);
1474 for (
int i = 0; i <
N_IIF; i++)
1478 double restore_time =
timing(t1, t0);
1479 log_msg(
logger, 0, 0,
"State restored from file %s in %.3f seconds.\n", fname, restore_time);
1496 char *reg_name,
char *sv_lst,
char *plg_lst,
1497 char *plg_sv_lst,
double t,
double dump_dt) {
1498 char file[8000], svs[1024], plgs[1024], plgsvs[1024];
1499 char *e, *l, *p, *svnames, *plgnames, *plgsvnames;
1501 strcpy(svs, sv_lst);
1502 strcpy(plgs, plg_lst);
1503 strcpy(plgsvs, plg_sv_lst);
1505 plgnames = &plgs[0];
1506 plgsvnames = &plgsvs[0];
1516 snprintf(file,
sizeof file,
"%s.%s.bin", reg_name, svnames);
1530 snprintf(file,
sizeof file,
"%s_%s.%s.bin", reg_name, plgnames, plgsvnames);
1555 const char *
filename,
const char *regname) {
1557 int n = this->
svd.
n;
1562 for (i = 0; i < IF->
plugins().size(); i++)
1563 if (IF->
plugins()[i]->get_type() == type)
1565 if (i == IF->
plugins().size()) {
1566 log_msg(
logger, 2, 0,
"Warning: IMP %s not found in Region %s\n",
1577 this->
svd.
fn =
static_cast<char **
>(realloc(this->
svd.
fn, this->svd.n*
sizeof(
char *)));
1578 this->
svd.
reg =
static_cast<int *
>(realloc(this->
svd.
reg, this->svd.n*
sizeof(
int)));
1579 this->
svd.
svnames =
static_cast<char **
>(realloc(this->
svd.
svnames, this->svd.n*
sizeof(
char *)));
1582 this->
svd.
offset =
static_cast<int *
>(realloc(this->
svd.
offset, this->svd.n*
sizeof(
int)));
1583 this->
svd.
size =
static_cast<int *
>(realloc(this->
svd.
size, this->svd.n*
sizeof(
int)));
1584 this->
svd.
dtype =
static_cast<int *
>(realloc(this->
svd.
dtype, this->svd.n*
sizeof(
int)));
1585 this->
svd.
svtab =
static_cast<void **
>(realloc(this->
svd.
svtab, this->svd.n*
sizeof(
void *)));
1586 this->
svd.
svsize =
static_cast<size_t *
>(realloc(this->
svd.
svsize, this->svd.n*
sizeof(
size_t)));
1587 this->
svd.
num =
static_cast<int *
>(realloc(this->
svd.
num, this->svd.n*
sizeof(
int)));
1588 this->
svd.
reg =
static_cast<int *
>(realloc(this->
svd.
reg, this->svd.n*
sizeof(
int)));
1601 this->
svd.
reg[n] = region;
1622 char *svname,
char *regname,
char *
filename) {
1623 int offset, size, dtype, added = 0;
1624 char *svtypename = NULL;
1628 filename_bin = strcat(
filename,
".bin");
1630 assert(type != NULL);
1633 this->
sv_dump_add(region, *type, offset, size, dtype, filename_bin, regname);
1637 log_msg(NULL, 1, 0,
"No state variable added to dump list");
1656 assert(miif->
gdata[Vm] != NULL);
1658 for (
int i = 0; i < NUM_IMP_DATA_TYPES; i++) {
1659 for (
int n = 0; n < miif->
N_IIF; n++)
1660 if (
USED_DAT(miif->
IIF[n], imp_data_flag[i]) && (miif->
gdata[i] == NULL)) {
1675 int num_mech_data = 0;
1677 for (
int i = 0; i < NUM_IMP_DATA_TYPES; i++) {
1678 if ( (Lambda_DATA_FLAG == i) || (delLambda_DATA_FLAG == i) ||
1679 (Tension_DATA_FLAG == i) || (tension_component_DATA_FLAG == i) ) {
1680 for (
int n = 0; n < this->
N_IIF; n++)
1685 return static_cast<bool>(num_mech_data);
1706 float beta,
int *node,
int numnode) {
1708 if (strstr(species,
"Ca") != NULL) {
1711 }
else if (strstr(species,
"Na") != NULL) {
1713 }
else if (strstr(species,
"Cl") != NULL) {
1715 }
else if (strstr(species,
"K") != NULL) {
1718 log_msg(
logger, 5, 0,
"Unimplemented ion species: %s\n", species);
1724 static int warned = 0;
1729 int my_low_idx = layout[rank], my_high_idx = layout[rank+1];
1731 for (
int i = 0; i < numnode; i++) {
1732 if ((node[i] < my_low_idx) || (node[i] >= my_high_idx))
continue;
1734 for (
int j = 0; j < this->
N_IIF; j++) {
1735 if (this->
NodeLists[j] == NULL)
continue;
1737 if ((node[i] < this->
NodeLists[j][0]) ||
1741 ion_get = this->
IIF[j]->get_type().get_sv_offset(species, &offset, &sz);
1742 if (ion_get == NULL) {
1745 log_msg(
logger, 2, 0,
"Ion species not present in ionic model: %s\n",
1757 stim_curr = curr*g.
sl_i2c/z;
1760 stim_curr = curr*beta/
FARADAY/z*1.e-2;
1763 for (
int k = 0; k < this->
N_Nodes[j]; k++)
1765 ion_put(*this->
IIF[j], k, offset, ion_get(*this->
IIF[j], k, offset)-stim_curr);
1778 for (
int i = 0; i < this->
N_IIF; i++) {
1779 this->
IIF[i]->destroy_luts();
1780 this->
IIF[i]->set_dt((
float) Dt);
1781 this->
iontypes[i].get().construct_tables(*this->
IIF[i]);
1783 for (
int j = 0; j < this->
IIF[i]->plugins().size(); j++) {
1784 auto& plugin = this->
IIF[i]->plugins()[j];
1785 plugin->destroy_luts();
1786 plugin->set_dt((
float) Dt);
1787 this->
plugtypes[i][j].get().construct_tables(*plugin);
1792 #define MEMFREE(A) free(A)
1803 for (
int i = 0; i < m->
N_IIF; i++) {
1804 m->
IIF[i]->get_type().destroy_ion_if(m->
IIF[i]);
1807 for (
int j = 0; j < NUM_IMP_DATA_TYPES; j++) {
1828 for (
int i = 0; i < NUM_IMP_DATA_TYPES; i++)
1832 for (
int i = 0; i < orig->
N_IIF; i++) {
1833 miif_doppel->
IIF[i]->copy_SVs_from(*orig->
IIF[i],
false);
1835 for (
int j = 0; j < orig->
IIF[i]->plugins().size(); j++)
1836 miif_doppel->
IIF[i]->plugins()[j]->copy_SVs_from(*orig->
IIF[i]->plugins()[j],
false);
1853 *miif_doppel = *orig;
1854 miif_doppel->
doppel =
true;
1857 for (
int i = 0; i < NUM_IMP_DATA_TYPES; i++)
1862 miif_doppel->
IIF = {};
1864 for (
int i = 0; i < orig->
N_IIF; i++) {
1866 miif_doppel->
IIF.push_back(orig->
IIF[i]->get_type().make_ion_if(orig->
IIF[i]->get_target(),
1868 miif_doppel->
IIF[i]->copy_SVs_from(*orig->
IIF[i],
true);
1869 miif_doppel->
IIF[i]->copy_plugins_from(*orig->
IIF[i]);
1892 int imp_data_id = -1;
1894 for (
int i = 0; i < NUM_IMP_DATA_TYPES; i++) {
1895 if (strcmp(sv, imp_data_names[i]) == 0) {
1910 for (
int i = 0; i < NUM_IMP_DATA_TYPES; i++)
1911 if (localdata && localdata[i])
1912 localdata[i][to] = localdata[i][from];
1916 int sv_list_size = imp.
get_type().get_sv_list(&sv_list);
1918 for (
int i = 0; i < sv_list_size; i++) {
1919 char *sv_name = sv_list[i];
1922 SVgetfcn sv_get = imp.
get_type().get_sv_offset(sv_name, &sv_offset, &sv_size);
1923 if (sv_get == NULL) {
1924 throw std::runtime_error(std::string(__func__) +
" error: " + sv_name +
" is not a valid state variable for the " + imp.
get_type().
get_name() +
" model.");
1929 sv_put(imp, to, sv_offset, sv_val);
#define NDEF
definition of cell geometry
#define MAX_TRACE_LINE_LEN
Define multiple ionic models to be used in different regions.
#define FARADAY
Faraday's constant.
double SF_real
Use the general double as real type.
#define SLIST_APPEND(S, P)
virtual void release_ptr(S *&p)=0
size_t read_binary(FILE *fd)
virtual void set(const vector< T > &idx, const vector< S > &vals, const bool additive=false)=0
virtual void add_scaled(const abstract_vector< T, S > &vec, S k)=0
size_t write_binary(FILE *fd)
Write a vector to HD in binary. File descriptor is already set up.
bool in_b(const T idx)
return whether idx is in set B
T backward_map(T idx) const
Map one index from b to a.
overlapping_layout< T > pl
nodal parallel layout
Container for a PETSc VecScatter.
void forward(abstract_vector< T, S > &in, abstract_vector< T, S > &out, bool add=false)
Forward scattering.
size_t size() const
The current size of the vector.
void resize(size_t n)
Resize a vector.
T * data()
Pointer to the vector's start.
Represents the ionic model and plug-in (IMP) data structure.
const IonType & get_type() const
Gets this IMP's model type.
std::vector< IonIfBase * > & plugins()
Returns a vector containing the plugins of this IMP.
ts & get_tstp()
Gets the time stepper.
void for_each(const std::function< void(IonIfBase &)> &consumer)
Executes the consumer functions on this IMP and each of its plugins.
IonIfBase * parent() const
Gets the parent IMP.
int get_num_node() const
Gets the number of nodes handled by this IMP.
int miifIdx
imp index within miif
virtual std::size_t get_sv_size() const =0
Gets the size of the structure this IMP uses for state variables.
virtual void * get_sv_address()=0
Gets the raw address of the state variables for this IMP.
void compute(int start, int end, GlobalData_t **data)
Perform ionic model computation for 1 time step.
Abstract class representing an ionic model type.
bool is_plugin() const
Returns whether this model is a plugin or not.
const std::string & get_name() const
Gets the model name.
virtual SVgetfcn get_sv_offset(const char *svname, int *off, int *sz) const =0
Get the offset and size of a state variable of the model, as well as an access function.
virtual int get_sv_type(const char *svname, int *type, char **type_name) const =0
Determines the type of a SV.
virtual size_t dlo_vector_size() const =0
Gets the vector size when using data layout optimization (DLO).
int numNode
local number of nodes
bool extUpdateVm
flag indicating update function for Vm
int dump_svs(opencarp::base_timer *)
std::vector< IonIfBase * > IIF
array of IIF's
opencarp::sf_vec * gdata[NUM_IMP_DATA_TYPES]
data used by all IMPs
void sv_dump_add_by_name_list(int, char *, char *, char *, char *, char *, double, double)
std::vector< Target > targets
target for each region
std::vector< IonTypeList > plugtypes
plugins types for each region
IonTypeList iontypes
type for each region
void dump_state(char *, float, opencarp::mesh_t gid, bool, unsigned int)
SV_DUMP svd
state variable dump
void sv_dump_add(int, const IonType &, int, int, int, const char *, const char *)
void transmem_stim_species(float, const char *, float, int *, int)
void initialize_currents(double, int)
GlobalData_t *** ldata
data local to each IMP
int adjust_MIIF_variables(const char *variable, const SF::vector< int > &indices, const SF::vector< double > &values)
float restore_state(const char *, opencarp::mesh_t gid, bool)
int N_IIF
how many different IIF's
void compute_ionic_current(bool flag_send=1, bool flag_receive=1)
GPU kernel to emulate the add_scaled call made to adjust the Vm values when the update to Vm is not m...
int sv_dump_add_by_name(int, char *, char *, char *, char *)
Trace_Info * trace_info
Information about traces.
int * N_Nodes
#nodes for each IMP
int ** NodeLists
local partitioned node lists for each IMP stored
GlobalData_t * procdata[NUM_IMP_DATA_TYPES]
data for this processor
void dump_luts_MIIF(bool)
bool * contiguous
whether a region is contiguously numbered
opencarp::FILE_SPEC logger
int numSubDt
number of sub-dt time steps
void MIIF_change_dt(double)
IIF_Mask_t * IIFmask
region for each node
std::string name
name for MIIF region
bool doppel
is this a shallow clone?
void releaseRealDataDuringInit()
void dsp_from_cnt(const vector< T > &cnt, vector< T > &dsp)
Compute displacements from counts.
T sum(const vector< T > &vec)
Compute sum of a vector's entries.
void local_petsc_to_nodal_mapping(const meshdata< T, S > &mesh, index_mapping< T > &petsc_to_nodal)
void layout_from_count(const T count, vector< T > &layout, MPI_Comm comm)
void init_vector(SF::abstract_vector< T, S > **vec)
@ NBR_SUBMESH
Submesh nodal numbering: The globally ascending sorted reference indices are reindexed.
void doppel_MIIF(MULTI_IF *orig, MULTI_IF *miif_doppel)
int getGlobalNodalIndex(IonIfBase &pIF, int relIdx)
void initializeIMPData(MULTI_IF *pMIIF)
int determine_write_ranges(int N, size_t *offset, size_t bufsize, int **ranges)
int get_plug_flag(char *plgstr, int *out_num_plugins, IonTypeList &out_plugins)
GlobalData_t(* SVgetfcn)(IonIfBase &, int, int)
SVputfcn getPutSV(SVgetfcn)
void doppel_update(MULTI_IF *orig, MULTI_IF *miif_doppel)
void dup_IMP_node_state(IonIfBase &IF, int from, int to, GlobalData_t **localdata)
int should_print_bounds_exceeded_messages()
@ CPU
baseline CPU model generated with the original opencarp code generator
IonType * get_ion_type(const std::string &name)
int IMPdataLabel2Index(const char *sv)
void CreateIIFGlobalNodeLsts(MULTI_IF *pMIIF)
void allocate_shared_data(MULTI_IF *)
bool isIMPdata(const char *)
bool is_gpu(Target const target)
Checks if this is a GPU target.
int current_global_node(int local_node)
void initialize_params_MIIF(MULTI_IF *pMIIF)
void(* SVputfcn)(IonIfBase &, int, int, GlobalData_t)
char * get_sv(void *tab, int offset, int n, int svSize, int size)
void alloc_MIIF(MULTI_IF *pMIIF)
void freeIMPData(MULTI_IF *pMIIF)
std::vector< std::reference_wrapper< IonType > > IonTypeList
constexpr T max(T a, T b)
void deallocate_on_target(Target target, T *ptr)
Utility function for deallocating memory on a target. See TargetAllocator.
void CreateIIFNodeLsts_(int, char *, int **, int ***, int)
void CreateIIFLocalNodeLsts(MULTI_IF *pMIIF)
void initialize_ionic_IF(MULTI_IF *pMIIF)
void update_ts(ts *ptstp)
float current_global_time()
void close_trace(MULTI_IF *MIIF)
void dump_trace(MULTI_IF *MIIF, limpet::Real time)
char * get_next_list(char *lst, char delimiter)
int int_cmp(const void *a, const void *b)
void open_trace(MULTI_IF *MIIF, int n_traceNodes, int *traceNodes, int *label, opencarp::sf_mesh *imesh)
Set up ionic model traces at some global node numbers.
void free_doppel(MULTI_IF *m)
char * tokstr_r(char *s1, const char *s2, char **lasts)
int set_print_bounds_exceeded_messages(int newval)
SF::abstract_vector< mesh_int_t, double > sf_vec
sf_mesh & get_mesh(const mesh_t gt)
Get a mesh by specifying the gridID.
SF::scattering * get_permutation(const int mesh_id, const int perm_id, const int dpn)
Get the PETSC to canonical permutation scattering for a given mesh and number of dpn.
SF::meshdata< mesh_int_t, mesh_real_t > sf_mesh
char * read_bin_string(FILE_SPEC in)
void f_read_par(void *ptr, size_t size, size_t nmemb, FILE_SPEC stream, MPI_Comm comm)
Parallel fread. Root reads, then broadcasts.
int get_rank(MPI_Comm comm=PETSC_COMM_WORLD)
T get_global(T in, MPI_Op OP, MPI_Comm comm=PETSC_COMM_WORLD)
Do a global reduction on a variable.
void write_bin_string(FILE_SPEC out, const char *s)
FILE_SPEC f_open(const char *fname, const char *mode)
Open a FILE_SPEC.
char * read_bin_string_par(FILE_SPEC in)
char * dupstr(const char *old_str)
void log_msg(FILE_SPEC out, int level, unsigned char flag, const char *fmt,...)
mesh_t
The enum identifying the different meshes we might want to load.
void get_time(double &tm)
int get_size(MPI_Comm comm=PETSC_COMM_WORLD)
V timing(V &t2, const V &t1)
void f_close(FILE_SPEC &f)
Close a FILE_SPEC.
#define PETSC_TO_CANONICAL
Permute algebraic data from PETSC to canonical ordering.
int offset
offset into node data
int map
which plugin does this IMO match
bool compatible
does IM match stored IM
int nplug
number of plugins
data structure to manage state variable file dumps
size_t * svsize
state variable sizes
char ** fn
array to store file names
double intv
time interval for sv dumps
int n_dumps
keep track of number of dumped time slices
long nwr
keep track of number of written tokens
int * size
sizes of SV to dump
void ** svtab
state variable tables
int * reg
array to store region ids
double t_dump
next instant for sv dump
char ** svnames
array to store sv names
int n
#state variables we want to dump
int * offset
offsets into structure for SV
opencarp::FILE_SPEC * hdls
array of file handles to sv output files
data structure to manage trace dumps. Should eventually be combined with the state variable dumps,...
bool ignored
globally not found
bool found
found on this node
int node_idx
local node number
float sl_i2c
convert sl-currents in uA/cm^2 to mM/L without valence