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++)
516 #endif // ifndef USE_HDF5 530 char *
get_sv(
void *tab,
int offset,
int n,
int svSize,
int size,
int dlo_vector_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 += dlo_vector_size) {
536 int dlo_array_size =
min(dlo_vector_size, n - i);
537 memcpy(bp, p, size * dlo_array_size);
538 bp += size * dlo_array_size;
554 if (iot->triggered) {
555 for (
int i = 0; i <
svd.
n; i++) {
560 nwr += SF::root_write<char>(fd, (
char*) buf,
svd.
size[i]*
svd.
num[i], PETSC_COMM_WORLD);
577 void update_vm(
int start,
int end,
double *vm,
double *ion,
double dt)
579 int i = blockIdx.x*blockDim.x + threadIdx.x;
581 vm[i] = vm[i] + (ion[i] * (-
dt));
589 if (flag_send == 1) {
593 for (
int j = 0; j < this->
numSubDt; j++)
595 for (
int i = 0; i < this->
N_IIF; i++)
598 if (!this->
N_Nodes[i])
continue;
600 prepare_error_recovery(
this, i, pIF->
get_tstp().
cnt * this->
dt);
612 fprintf(stderr,
"LIMPET compute fail in %s at node %d (local %d)! Aborting!\n",
618 }
while (current < this->
N_Nodes[i]);
620 for (
auto& plugin : pIF->
plugins()) {
626 plugin->compute(current, this->
N_Nodes[i], this->
ldata[i]);
629 if (plugin ==
nullptr)
635 fprintf(stderr,
"LIMPET plugin fail in %s at node %d (local %d)! Aborting!\n",
641 }
while (current < this->
N_Nodes[i]);
650 #if defined __CUDA__ || defined __HIP__ 653 cudaDeviceSynchronize();
654 #elif defined __HIP__ 655 hipDeviceSynchronize();
658 fprintf(stderr,
"GPU/CUDA not found");
663 if (flag_receive == 1) {
678 for (
auto& pIF : this->
IIF) {
679 pIF->get_type().destroy_ion_if(pIF);
690 for (
int i = 0; i < pMIIF->
N_IIF; i++) {
698 for (
int j = 0; j < NUM_IMP_DATA_TYPES; j++) {
706 allocate_on_target<GlobalData_t>(pMIIF->
IIF[i]->get_target(),
709 if (pMIIF->
gdata[j] == NULL) {
710 log_msg(pMIIF->
logger, 5,
LOCAL,
"IMP data type %s not supplied for region %d", imp_data_names[j], i);
728 for (
int j = 0; j < NUM_IMP_DATA_TYPES; j++) {
730 if (this->
gdata[j] != NULL) {
738 for (
int i = 0; i < this->
N_IIF; i++) {
746 for (
int k = 0; k < this->
N_Nodes[i]; k++)
747 this->
ldata[i][j][k] = rdata[ip[k]];
763 for (
int i = 0; i < this->
N_IIF; i++) {
764 if (!this->
N_Nodes[i])
continue;
767 if (
is_gpu(this->
IIF[i]->get_target())) {
768 for (
int j = 0; j < NUM_IMP_DATA_TYPES; j++) {
774 for (
int k = 0; k < this->
N_Nodes[i]; k++)
780 for (
int j = 0; j < NUM_IMP_DATA_TYPES; j++) {
781 if (this->
IIF[i]->get_moddat() & imp_data_flag[j]) {
783 for (
int k = 0; k < this->
N_Nodes[i]; k++)
791 for (
int j = 0; j < NUM_IMP_DATA_TYPES; j++)
792 if (this->
gdata[j] != NULL)
798 for (
int j = 0; j < NUM_IMP_DATA_TYPES; j++) {
799 if (pMIIF->
gdata[j] != NULL) {
800 for (
int i = 0; i < pMIIF->
N_IIF; i++)
802 deallocate_on_target<GlobalData_t>(pMIIF->
IIF[i]->get_target(),
805 delete pMIIF->
gdata[j];
822 if (plgstr == NULL) {
823 *out_num_plugins = 0;
829 char *plugspec =
dupstr(plgstr);
831 char *token =
tokstr_r(plugspec,
":", &saveptr);
833 *out_num_plugins = 0;
840 out_plugins.push_back(*type);
842 token =
tokstr_r(NULL,
":", &saveptr);
845 *out_num_plugins = out_plugins.size();
876 if (index(variable,
'.') == NULL) {
880 for (
int ii = 0; ii < NUM_IMP_DATA_TYPES; ii++) {
881 if (strcmp(variable, imp_data_names[ii]) == 0) {
887 log_msg(
logger, 5,
FLUSH,
"Error! No external variable named %s in this build of openCARP.", variable);
892 if (this->
gdata[data_id] == NULL) {
894 "External variable %s is not being used this processor.\n" 895 "Is this really what you meant to do?\n" 896 "Perhaps you don't have the correct Ionic models selected.",
897 imp_data_names[data_id]);
903 for (
size_t i = 0; i < indices.
size(); i++) {
904 raw_data[indices[i]] = values[i];
915 char *my_variable =
dupstr(variable);
916 char *IIF_name =
tokstr_r(my_variable,
".", &saveptr);
917 char *sv_name =
tokstr_r(NULL,
".", &saveptr);
921 log_msg(
logger, 5, 0,
"%s error: %s is not a valid IMP name.", __func__, IIF_name);
928 if (sv_get == NULL) {
929 log_msg(
logger, 5, 0,
"%s error: %s is not a valid state variable for the %s model.",
930 __func__, sv_name, IIF_name);
936 for (
int i_iif = 0; i_iif < this->
N_IIF; i_iif++) {
938 if (this->
IIF[i_iif]->get_type() == *type) {
939 lIIF = this->
IIF[i_iif];
943 for (
auto& plugin : this->
IIF[i_iif]->plugins()) {
944 if (plugin->get_type() == *type) {
955 for (
size_t ii = 0; ii < indices.
size(); ii++) {
958 int *target =
static_cast<int*
>(bsearch(&indices[ii], this->
NodeLists[i_iif],
963 sv_put(*lIIF, (
int)(target - this->
NodeLists[i_iif]), sv_offset, file_value);
971 MPI_Allreduce(MPI_IN_PLACE, &num_changed, 1, MPI_INT, MPI_SUM, PETSC_COMM_WORLD);
1000 long loff = offset[0];
1001 for (
int i = 0; i < N; i++)
1002 if (offset[i]-loff > bufsize) {
1009 *ranges = (
int *)r.data;
1012 MPI_Bcast(&nitems, 1, MPI_INT, 0, PETSC_COMM_WORLD);
1014 *ranges =
static_cast<int *
>(malloc( (nitems+1)*
sizeof(
int) ));
1015 MPI_Bcast(*ranges, nitems+1, MPI_INT, 0, PETSC_COMM_WORLD);
1058 bool append,
unsigned int revision)
1068 log_msg(
logger, 0, 0,
"Saving state at time %f in file: %s", simtime, fname);
1071 out =
f_open(fname, append ?
"a" :
"w");
1074 fseek(out->fd, 0, SEEK_END);
1077 fwrite(&MIIF_Format,
sizeof(
unsigned int), 1, out->fd);
1078 fwrite(&revision,
sizeof(
unsigned int), 1, out->fd);
1079 time_t tm = time(NULL);
1080 fwrite(&tm,
sizeof(time_t), 1, out->fd);
1081 fwrite(&simtime,
sizeof(
float), 1, out->fd);
1082 fwrite(&miif_node_gsize,
sizeof(
int), 1, out->fd);
1085 for (
int i = 0; i < NUM_IMP_DATA_TYPES; i++)
1086 if (this->
gdata[i]) num_gdata++;
1088 fwrite(&num_gdata,
sizeof(
int), 1, out->fd);
1099 FILE* fd = rank == 0 ? out->fd : NULL;
1102 for (
int i = 0; i < NUM_IMP_DATA_TYPES; i++) {
1103 if (this->
gdata[i]) {
1107 log_msg(NULL, 0, 0,
"\tDumping %s at %d", imp_data_names[i], ftell(fd) );
1120 outVec->write_binary<
SF_real>(fd);
1132 int* imp_mem =
new int[this->
N_IIF];
1133 size_t *offset = NULL;
1138 log_msg(NULL, 0, 0,
"\tDumping IMP sizes at %d", ftell(fd) );
1142 fwrite(&this->
N_IIF,
sizeof(
int), 1, fd);
1144 for (
int i = 0; i < this->
N_IIF; i++) {
1149 fwrite(&sv_size,
sizeof(
int), 1, fd);
1150 unsigned long n_plugins = (
unsigned long) imp->
plugins().size();
1151 fwrite(&n_plugins,
sizeof(
int), 1, fd);
1154 for (
auto& plug : imp->
plugins()) {
1157 fwrite(&sv_size,
sizeof(
int), 1, fd);
1158 imp_mem[i] += plug->get_sv_size();
1161 filepos = ftell(fd);
1164 MPI_Bcast(imp_mem, this->
N_IIF, MPI_INT, 0, PETSC_COMM_WORLD);
1177 for(
size_t i=0; i<alg_idx.
size(); i++) loc2canon[i] = canon_nbr[alg_idx[i]];
1185 for (
int i = 0; i < this->
numNode; i++) loc2canon[i] = layout[rank] + i;
1189 int *canord =
new int[this->
numNode];
1190 for (
int i = 0; i < this->
numNode; i++)
1191 canord[i] = loc2canon[i];
1194 log_msg(NULL, 0, 0,
"\tDumping IMP masks at %d", filepos);
1195 #endif // ifdef CHATTY 1197 SF::root_write_ordered<int, IIF_Mask_t>(fd, canord,
IIFmask,
numNode, PETSC_COMM_WORLD);
1203 impsize[i] = imp_mem[(
int)IIFmask[i]];
1207 size_t num_entr =
SF::sum(impsize);
1211 for (
int imp_idx = 0; imp_idx < this->
N_IIF; imp_idx++)
1217 for (
int imp_nod_idx = 0; imp_nod_idx < this->
N_Nodes[imp_idx]; imp_nod_idx+=vec_size) {
1218 int index = imp_nod_idx / vec_size;
1219 int loc = this->
NodeLists[imp_idx][imp_nod_idx];
1222 char* write = impdata.
data() + impdsp[loc];
1224 memcpy(write, read, svSize);
1227 for (
auto& plug : iif->
plugins()) {
1228 int plugsize = plug->get_sv_size();
1230 write = impdata.
data() + impdsp[loc] + shift;
1231 read = (
char*) plug->get_sv_address() + index * plugsize;
1232 memcpy(write, read, plugsize);
1239 SF::root_write_ordered<int, char>(fd, canord, impsize.data(), impdata.
data(),
1240 numNode, num_entr, PETSC_COMM_WORLD);
1246 double dump_time =
timing(t1, t0);
1275 static char *last_fn = NULL;
1284 if (fname) in =
f_open(fname,
"r");
1287 if (fname)
log_msg(
logger, 5, 0,
"Error: cannot open file: %s\n", fname);
1288 else log_msg(
logger, 5, 0,
"Error: file stream not open yet");
1293 log_msg(
logger, 5, 0,
"%s is not a recognized MIIF dump file", fname);
1304 last_fn = strdup(fname);
1310 unsigned int format, version;
1313 f_read_par(&format,
sizeof(
unsigned int), 1, in);
1314 f_read_par(&version,
sizeof(
unsigned int), 1, in);
1315 f_read_par(&save_date,
sizeof(time_t), 1, in);
1317 log_msg(
logger, 0, 0,
"Restoring time %f from %s (format v%d) generated\n\tby calling " 1318 "program r%d on %s", time, fname, format, version, ctime(&save_date) );
1320 int savedNum, glob_numNode;
1321 MPI_Allreduce(&this->
numNode, &glob_numNode, 1, MPI_INT, MPI_SUM, PETSC_COMM_WORLD);
1324 if (savedNum != glob_numNode) {
1325 log_msg(
logger, 5, 0,
"expecting %d nodes but read %d nodes", glob_numNode, savedNum);
1333 for (
int g = 0; g < num_gdata; g++) {
1336 for (i = 0; i < NUM_IMP_DATA_TYPES; i++) {
1337 if (!strcmp(datatype, imp_data_names[i]) ) {
1338 if (this->
gdata[i]) {
1339 log_msg(
logger, 0, 0,
"\tRestoring global data %s", imp_data_names[i], datatype);
1341 FILE* fd = my_rank == 0 ? in->fd : NULL;
1344 petsc2canon(*this->
gdata[i], fwd);
1346 log_msg(
logger, 0, 0,
"\tGlobal data %s not used", datatype);
1351 if (i == NUM_IMP_DATA_TYPES)
1352 log_msg(
logger, 3, 0,
"\tSaved global data %s not recognized", datatype);
1354 if ( (my_rank == 0) && ((i == NUM_IMP_DATA_TYPES) || !this->
gdata[i]) )
1355 fseek(in->fd, this->gdata[i]->gsize() *
sizeof(
SF_real), SEEK_CUR);
1365 int *IMPsz =
static_cast<int *
>(malloc(N_IIF *
sizeof(
int)));
1367 for (
int i = 0; i <
N_IIF; i++) {
1370 f_read_par(&imps[i].nplug,
sizeof(
int), 1, in);
1373 IMPsz[i] = imps[i].
sz;
1376 for (
int j = 0; j < imps[i].
nplug; j++) {
1379 f_read_par(&imps[i].plug[j].sz,
sizeof(
int), 1, in);
1380 IMPsz[i] += imps[i].
plug[j].
sz;
1385 for (
int i = 0; i <
N_IIF; i++) {
1386 if (i >= this->N_IIF) {
1387 log_msg(NULL, 3, 0,
"Saved IMP region %d out of range", i);
1390 if (strcmp(imps[i].
name, this->
IIF[i]->get_type().get_name().c_str()) ) {
1391 log_msg(NULL, 3, 0,
"Saved IMP region %d ionic model does not match that of IMP region %d", i, i);
1394 if (imps[i].sz != this->
IIF[i]->get_sv_size()) {
1395 log_msg(NULL, 3, 0,
"Saved IMP region %d size does not match current IMP size", i);
1401 for (
int j = 0; j < imps[i].
nplug; j++)
1402 for (
int k = 0; k < this->
IIF[i]->plugins().size(); k++)
1403 if (!strcmp(imps[i].plug[j].name, this->
IIF[i]->plugins()[k]->get_type().get_name().c_str()) &&
1404 (imps[i].
plug[j].
sz == this->
IIF[i]->plugins()[k]->get_sv_size()) ) {
1405 log_msg(NULL, 3, 0,
"Saved IMP region %d plugin %s compatible", i, imps[i].plug[j].name);
1414 IIF_Mask_t *canMask =
static_cast<char *
>(malloc(glob_numNode*
sizeof(this->
IIFmask[0]) ));
1418 size_t *offset =
static_cast<size_t *
>(calloc(glob_numNode+1,
sizeof(
size_t)));
1419 for (
int i = 1; i <= glob_numNode; i++)
1420 offset[i] = offset[i-1] + IMPsz[static_cast<int>(canMask[i-1])];
1428 SVstart = ftell(in->fd);
1432 MPI_Bcast(&SVstart,
sizeof(
long), MPI_BYTE, 0, PETSC_COMM_WORLD);
1441 for(
size_t i=0; i<alg_idx.
size(); i++) loc2canon[i] = canon_nbr[alg_idx[i]];
1444 for (
int pid = 0; pid < mpi_size; pid++) {
1445 if (my_rank == pid) {
1449 for (
int i = 0; i <
N_IIF; i++) {
1450 fseek(in->fd, SVstart, SEEK_SET);
1452 canMask, offset, imps+i, loc2canon.data());
1457 MPI_Barrier(PETSC_COMM_WORLD);
1462 MPI_Reduce(my_rank ? &mismatch : MPI_IN_PLACE, &mismatch, 1, MPI_INT, MPI_SUM, 0, PETSC_COMM_WORLD);
1463 if ( (my_rank == 0) && mismatch)
1464 log_msg(NULL, 3, 0,
"Number of nonmatching nodes: %d", mismatch);
1466 if ( (my_rank == 0) && (!close) ) {
1471 fseek(in->fd, SVstart+offset[glob_numNode], SEEK_SET);
1475 for (
int i = 0; i <
N_IIF; i++)
1479 double restore_time =
timing(t1, t0);
1480 log_msg(
logger, 0, 0,
"State restored from file %s in %.3f seconds.\n", fname, restore_time);
1497 char *reg_name,
char *sv_lst,
char *plg_lst,
1498 char *plg_sv_lst,
double t,
double dump_dt) {
1499 char file[8000], svs[1024], plgs[1024], plgsvs[1024];
1500 char *e, *l, *p, *svnames, *plgnames, *plgsvnames;
1502 strcpy(svs, sv_lst);
1503 strcpy(plgs, plg_lst);
1504 strcpy(plgsvs, plg_sv_lst);
1506 plgnames = &plgs[0];
1507 plgsvnames = &plgsvs[0];
1517 snprintf(file,
sizeof file,
"%s.%s.bin", reg_name, svnames);
1531 snprintf(file,
sizeof file,
"%s_%s.%s.bin", reg_name, plgnames, plgsvnames);
1556 const char *
filename,
const char *regname) {
1558 int n = this->
svd.
n;
1563 for (i = 0; i < IF->
plugins().size(); i++)
1564 if (IF->
plugins()[i]->get_type() == type)
1566 if (i == IF->
plugins().size()) {
1567 log_msg(
logger, 2, 0,
"Warning: IMP %s not found in Region %s\n",
1578 this->
svd.
fn =
static_cast<char **
>(realloc(this->
svd.
fn, this->svd.n*
sizeof(
char *)));
1579 this->
svd.
reg =
static_cast<int *
>(realloc(this->
svd.
reg, this->svd.n*
sizeof(
int)));
1580 this->
svd.
svnames =
static_cast<char **
>(realloc(this->
svd.
svnames, this->svd.n*
sizeof(
char *)));
1583 this->
svd.
offset =
static_cast<int *
>(realloc(this->
svd.
offset, this->svd.n*
sizeof(
int)));
1584 this->
svd.
size =
static_cast<int *
>(realloc(this->
svd.
size, this->svd.n*
sizeof(
int)));
1585 this->
svd.
dlo_vs =
static_cast<int *
>(realloc(this->
svd.
dlo_vs, this->svd.n*
sizeof(
int)));
1586 this->
svd.
dtype =
static_cast<int *
>(realloc(this->
svd.
dtype, this->svd.n*
sizeof(
int)));
1587 this->
svd.
svtab =
static_cast<void **
>(realloc(this->
svd.
svtab, this->svd.n*
sizeof(
void *)));
1588 this->
svd.
svsize =
static_cast<size_t *
>(realloc(this->
svd.
svsize, this->svd.n*
sizeof(
size_t)));
1589 this->
svd.
num =
static_cast<int *
>(realloc(this->
svd.
num, this->svd.n*
sizeof(
int)));
1590 this->
svd.
reg =
static_cast<int *
>(realloc(this->
svd.
reg, this->svd.n*
sizeof(
int)));
1597 #endif // ifdef HDF5 1603 this->
svd.
reg[n] = region;
1625 char *svname,
char *regname,
char *
filename) {
1626 int offset, size, dtype, added = 0;
1627 char *svtypename = NULL;
1631 filename_bin = strcat(filename,
".bin");
1633 assert(type != NULL);
1636 this->
sv_dump_add(region, *type, offset, size, dtype, filename_bin, regname);
1640 log_msg(NULL, 1, 0,
"No state variable added to dump list");
1659 assert(miif->
gdata[Vm] != NULL);
1661 for (
int i = 0; i < NUM_IMP_DATA_TYPES; i++) {
1662 for (
int n = 0; n < miif->
N_IIF; n++)
1663 if (
USED_DAT(miif->
IIF[n], imp_data_flag[i]) && (miif->
gdata[i] == NULL)) {
1678 int num_mech_data = 0;
1680 for (
int i = 0; i < NUM_IMP_DATA_TYPES; i++) {
1681 if ( (Lambda_DATA_FLAG == i) || (delLambda_DATA_FLAG == i) ||
1682 (Tension_DATA_FLAG == i) || (tension_component_DATA_FLAG == i) ) {
1683 for (
int n = 0; n < this->
N_IIF; n++)
1688 return static_cast<bool>(num_mech_data);
1709 float beta,
int *node,
int numnode) {
1711 if (strstr(species,
"Ca") != NULL) {
1714 }
else if (strstr(species,
"Na") != NULL) {
1716 }
else if (strstr(species,
"Cl") != NULL) {
1718 }
else if (strstr(species,
"K") != NULL) {
1721 log_msg(
logger, 5, 0,
"Unimplemented ion species: %s\n", species);
1727 static int warned = 0;
1732 int my_low_idx = layout[rank], my_high_idx = layout[rank+1];
1734 for (
int i = 0; i < numnode; i++) {
1735 if ((node[i] < my_low_idx) || (node[i] >= my_high_idx))
continue;
1737 for (
int j = 0; j < this->
N_IIF; j++) {
1738 if (this->
NodeLists[j] == NULL)
continue;
1740 if ((node[i] < this->
NodeLists[j][0]) ||
1744 ion_get = this->
IIF[j]->get_type().get_sv_offset(species, &offset, &sz);
1745 if (ion_get == NULL) {
1748 log_msg(
logger, 2, 0,
"Ion species not present in ionic model: %s\n",
1760 delta_conc = charge*g.
sl_i2c/z;
1763 delta_conc = charge*beta/
FARADAY/z*1.e-1;
1766 for (
int k = 0; k < this->
N_Nodes[j]; k++)
1768 ion_put(*this->
IIF[j], k, offset, ion_get(*this->
IIF[j], k, offset)-delta_conc);
1781 for (
int i = 0; i < this->
N_IIF; i++) {
1782 this->
IIF[i]->destroy_luts();
1783 this->
IIF[i]->set_dt((
float) Dt);
1784 this->
iontypes[i].get().construct_tables(*this->
IIF[i]);
1786 for (
int j = 0; j < this->
IIF[i]->plugins().size(); j++) {
1787 auto& plugin = this->
IIF[i]->plugins()[j];
1788 plugin->destroy_luts();
1789 plugin->set_dt((
float) Dt);
1790 this->
plugtypes[i][j].get().construct_tables(*plugin);
1795 #define MEMFREE(A) free(A) 1806 for (
int i = 0; i < m->
N_IIF; i++) {
1807 m->
IIF[i]->get_type().destroy_ion_if(m->
IIF[i]);
1810 for (
int j = 0; j < NUM_IMP_DATA_TYPES; j++) {
1831 for (
int i = 0; i < NUM_IMP_DATA_TYPES; i++)
1835 for (
int i = 0; i < orig->
N_IIF; i++) {
1836 miif_doppel->
IIF[i]->copy_SVs_from(*orig->
IIF[i],
false);
1838 for (
int j = 0; j < orig->
IIF[i]->plugins().size(); j++)
1839 miif_doppel->
IIF[i]->plugins()[j]->copy_SVs_from(*orig->
IIF[i]->plugins()[j],
false);
1856 *miif_doppel = *orig;
1857 miif_doppel->
doppel =
true;
1860 for (
int i = 0; i < NUM_IMP_DATA_TYPES; i++)
1865 miif_doppel->
IIF = {};
1867 for (
int i = 0; i < orig->
N_IIF; i++) {
1869 miif_doppel->
IIF.push_back(orig->
IIF[i]->get_type().make_ion_if(orig->
IIF[i]->get_target(),
1871 miif_doppel->
IIF[i]->copy_SVs_from(*orig->
IIF[i],
true);
1872 miif_doppel->
IIF[i]->copy_plugins_from(*orig->
IIF[i]);
1895 int imp_data_id = -1;
1897 for (
int i = 0; i < NUM_IMP_DATA_TYPES; i++) {
1898 if (strcmp(sv, imp_data_names[i]) == 0) {
1913 for (
int i = 0; i < NUM_IMP_DATA_TYPES; i++)
1914 if (localdata && localdata[i])
1915 localdata[i][to] = localdata[i][from];
1921 for (
int i = 0; i < sv_list_size; i++) {
1922 char *sv_name = sv_list[i];
1926 if (sv_get == NULL) {
1927 throw std::runtime_error(std::string(__func__) +
" error: " + sv_name +
" is not a valid state variable for the " + imp.
get_type().
get_name() +
" model.");
1932 sv_put(imp, to, sv_offset, sv_val);
constexpr T min(T a, T b)
GlobalData_t(* SVgetfcn)(IonIfBase &, int, int)
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.
int ** NodeLists
local partitioned node lists for each IMP stored
int node_idx
local node number
const std::string & get_name() const
Gets the model name.
The mesh storage class. It contains both element and vertex data.
bool compatible
does IM match stored IM
virtual void release_ptr(S *&p)=0
void releaseRealDataDuringInit()
char * dupstr(const char *old_str)
Trace_Info * trace_info
Information about traces.
virtual void add_scaled(const abstract_vector< T, S > &vec, S k)=0
void close_trace(MULTI_IF *MIIF)
int * offset
offsets into structure for SV
int n_dumps
keep track of number of dumped time slices
void local_petsc_to_nodal_mapping(const meshdata< T, S > &mesh, index_mapping< T > &petsc_to_nodal)
#define NDEF
definition of cell geometry
SV_DUMP svd
state variable dump
void layout_from_count(const T count, vector< T > &layout, MPI_Comm comm)
GlobalData_t * procdata[NUM_IMP_DATA_TYPES]
data for this processor
std::vector< std::reference_wrapper< IonType > > IonTypeList
int nplug
number of plugins
constexpr T max(T a, T b)
void sv_dump_add_by_name_list(int, char *, char *, char *, char *, char *, double, double)
#define PETSC_TO_CANONICAL
Permute algebraic data from PETSC to canonical ordering.
void CreateIIFNodeLsts_(int, char *, int **, int ***, int)
const IonType & get_type() const
Gets this IMP's model type.
IonIfBase * parent() const
Gets the parent IMP.
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...
void doppel_MIIF(MULTI_IF *orig, MULTI_IF *miif_doppel)
T backward_map(T idx) const
Map one index from b to a.
overlapping_layout< T > pl
nodal parallel layout
bool found
found on this node
IIF_Mask_t * IIFmask
region for each node
void dump_luts_MIIF(bool)
void f_read_par(void *ptr, size_t size, size_t nmemb, FILE_SPEC stream, MPI_Comm comm)
Parallel fread. Root reads, then broadcasts.
void(* SVputfcn)(IonIfBase &, int, int, GlobalData_t)
int sv_dump_add_by_name(int, char *, char *, char *, char *)
bool doppel
is this a shallow clone?
data structure to manage state variable file dumps
int n
#state variables we want to dump
std::string name
name for MIIF region
virtual int get_sv_type(const char *svname, int *type, char **type_name) const =0
Determines the type of a SV.
float restore_state(const char *, opencarp::mesh_t gid, bool)
void allocate_shared_data(MULTI_IF *)
void sv_dump_add(int, const IonType &, int, int, int, const char *, const char *)
data structure to manage trace dumps. Should eventually be combined with the state variable dumps...
SVputfcn getPutSV(SVgetfcn)
int * reg
array to store region ids
IonTypeList iontypes
type for each region
virtual std::size_t get_sv_size() const =0
Gets the size of the structure this IMP uses for state variables.
T * data()
Pointer to the vector's start.
float current_global_time()
int map
which plugin does this IMO match
mesh_t
The enum identifying the different meshes we might want to load.
int * size
sizes of SV to dump
int get_plug_flag(char *plgstr, int *out_num_plugins, IonTypeList &out_plugins)
std::vector< IonTypeList > plugtypes
plugins types for each region
int N_IIF
how many different IIF's
void initialize_currents(double, int)
bool is_gpu(Target const target)
Checks if this is a GPU target.
void write_bin_string(FILE_SPEC out, const char *s)
int should_print_bounds_exceeded_messages()
#define SLIST_APPEND(S, P)
void init_vector(SF::abstract_vector< T, S > **vec)
bool * contiguous
whether a region is contiguously numbered
std::vector< IonIfBase * > IIF
array of IIF's
int set_print_bounds_exceeded_messages(int newval)
void alloc_MIIF(MULTI_IF *pMIIF)
char * read_bin_string_par(FILE_SPEC in)
void ** svtab
state variable tables
void MIIF_change_dt(double)
long nwr
keep track of number of written tokens
int numSubDt
number of sub-dt time steps
void doppel_update(MULTI_IF *orig, MULTI_IF *miif_doppel)
void initialize_ionic_IF(MULTI_IF *pMIIF)
void dump_state(char *, float, opencarp::mesh_t gid, bool, unsigned int)
#define FARADAY
Faraday's constant.
Define multiple ionic models to be used in different regions.
char ** fn
array to store file names
Submesh nodal numbering: The globally ascending sorted reference indices are reindexed.
Represents the ionic model and plug-in (IMP) data structure.
IonType * get_ion_type(const std::string &name)
size_t * svsize
state variable sizes
int current_global_node(int local_node)
GlobalData_t *** ldata
data local to each IMP
void forward(abstract_vector< T, S > &in, abstract_vector< T, S > &out, bool add=false)
Forward scattering.
float sl_i2c
convert sl-currents in uA/cm^2 to mM/L without valence
virtual void set(const vector< T > &idx, const vector< S > &vals, const bool additive=false)=0
void free_doppel(MULTI_IF *m)
virtual int get_sv_list(char ***list) const =0
Returns a list of SVs.
void compute(int start, int end, GlobalData_t **data)
Perform ionic model computation for 1 time step.
sf_mesh & get_mesh(const mesh_t gt)
Get a mesh by specifying the gridID.
virtual size_t dlo_vector_size() const =0
Gets the vector size when using data layout optimization (DLO).
size_t write_binary(FILE *fd)
Write a vector to HD in binary. File descriptor is already set up.
size_t read_binary(FILE *fd)
char * read_bin_string(FILE_SPEC in)
char * get_next_list(char *lst, char delimiter)
int IMPdataLabel2Index(const char *sv)
int int_cmp(const void *a, const void *b)
bool in_b(const T idx)
return whether idx is in set B
SF::abstract_vector< SF_int, SF_real > sf_vec
void CreateIIFLocalNodeLsts(MULTI_IF *pMIIF)
void get_time(double &tm)
ts & get_tstp()
Gets the time stepper.
int getGlobalNodalIndex(IonIfBase &pIF, int relIdx)
T sum(const vector< T > &vec)
Compute sum of a vector's entries.
char * tokstr_r(char *s1, const char *s2, char **lasts)
double t_dump
next instant for sv dump
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.
T get_global(T in, MPI_Op OP, MPI_Comm comm=PETSC_COMM_WORLD)
Do a global reduction on a variable.
int * N_Nodes
#nodes for each IMP
void freeIMPData(MULTI_IF *pMIIF)
V timing(V &t2, const V &t1)
int dump_svs(opencarp::base_timer *)
void transmem_stim_species(float, const char *, float, int *, int)
int determine_write_ranges(int N, size_t *offset, size_t bufsize, int **ranges)
opencarp::sf_vec * gdata[NUM_IMP_DATA_TYPES]
data used by all IMPs
opencarp::FILE_SPEC * hdls
array of file handles to sv output files
int offset
offset into node data
void dup_IMP_node_state(IonIfBase &IF, int from, int to, GlobalData_t **localdata)
void for_each(const std::function< void(IonIfBase &)> &consumer)
Executes the consumer functions on this IMP and each of its plugins.
size_t size() const
The current size of the vector.
void initializeIMPData(MULTI_IF *pMIIF)
void initialize_params_MIIF(MULTI_IF *pMIIF)
baseline CPU model generated with the original opencarp code generator
void log_msg(FILE_SPEC out, int level, unsigned char flag, const char *fmt,...)
double intv
time interval for sv dumps
int get_num_node() const
Gets the number of nodes handled by this IMP.
std::vector< IonIfBase * > & plugins()
Returns a vector containing the plugins of this IMP.
void update_ts(ts *ptstp)
virtual void * get_sv_address()=0
Gets the raw address of the state variables for this IMP.
void dump_trace(MULTI_IF *MIIF, limpet::Real time)
std::vector< Target > targets
target for each region
int numNode
local number of nodes
void f_close(FILE_SPEC &f)
Close a FILE_SPEC.
bool isIMPdata(const char *)
bool ignored
globally not found
opencarp::FILE_SPEC logger
Abstract class representing an ionic model type.
double SF_real
Use the general double as real type.
int miifIdx
imp index within miif
bool extUpdateVm
flag indicating update function for Vm
void CreateIIFGlobalNodeLsts(MULTI_IF *pMIIF)
char ** svnames
array to store sv names
void resize(size_t n)
Resize a vector.
int adjust_MIIF_variables(const char *variable, const SF::vector< SF_int > &indices, const SF::vector< SF_real > &values)
int get_size(MPI_Comm comm=PETSC_COMM_WORLD)
bool is_plugin() const
Returns whether this model is a plugin or not.
#define MAX_TRACE_LINE_LEN
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.
void deallocate_on_target(Target target, T *ptr)
Utility function for deallocating memory on a target. See TargetAllocator.
char * get_sv(void *tab, int offset, int n, int svSize, int size, int dlo_vector_size)
void dsp_from_cnt(const vector< T > &cnt, vector< T > &dsp)
Compute displacements from counts.
SF::meshdata< mesh_int_t, mesh_real_t > sf_mesh
int get_rank(MPI_Comm comm=PETSC_COMM_WORLD)
FILE_SPEC f_open(const char *fname, const char *mode)
Open a FILE_SPEC.
Container for a PETSc VecScatter.