1 /* Steven Andrews, started 10/22/2001.
2  This is an application programming interface for the Smoldyn program.
3  See documentation called SmoldynManual.pdf and SmoldynCodeDoc.pdf, and the Smoldyn
4  website, which is at www.smoldyn.org.
5  Copyright 2003-2016 by Steven Andrews.  This work is distributed under the terms
6  of the Gnu Lesser General Public License (LGPL). */
7 
8 #include <string.h>
9 #include "../libSteve/List.h"
10 #include "opengl2.h"
11 #include "SimCommand.h"
12 #include "string2.h"
13 #include "List.h"
14 
15 #include "smoldyn.h"
16 #include "smoldynfuncs.h"
17 #include "libsmoldyn.h"
18 #ifdef OPTION_VCELL
19 	#include "SimpleValueProvider.h"
20 	#include "SimpleMesh.h"
21 #endif
22 
23 #define LCHECK(A,B,C,D) if(!(A)) {smolSetError(B,C,D,sim?sim->flags:"");if(C<ECwarning) goto failure;} else (void)0
24 #define LCHECKNT(A,B,C,D) if(!(A)) {smolSetErrorNT(B,C,D);if(C<ECwarning) goto failure;} else (void)0
25 
26 #ifdef __cplusplus
27     #define CSTRING "C"
28 #else
29     #define CSTRING
30 #endif
31 
32 
33 enum ErrorCode Liberrorcode=ECok;
34 enum ErrorCode Libwarncode=ECok;
35 char Liberrorfunction[STRCHAR]="";
36 char Liberrorstring[STRCHAR]="";
37 int Libdebugmode=1;
38 int LibThrowThreshold=11;
39 
40 PanelShape AllPanels_arr[6] = {PanelShape::PSrect, PanelShape::PStri,
41     PanelShape::PSsph, PanelShape::PScyl, PanelShape::PShemi, PanelShape::PSdisk};
42 
43 
44 /******************************************************************************/
45 /******************************* Miscellaneous ********************************/
46 /******************************************************************************/
47 
48 
49 /* smolGetVersion */
smolGetVersion(void)50 extern CSTRING double smolGetVersion(void) {
51 	return simversionnumber(); }
52 
53 
54 /******************************************************************************/
55 /*********************************** Errors ***********************************/
56 /******************************************************************************/
57 
58 /* smolSetLogging */
smolSetLogging(FILE * logfile,void (* logFunction)(simptr,int,const char *,...))59 extern CSTRING void smolSetLogging(FILE *logfile,void (*logFunction)(simptr,int,const char*,...)) {
60 	simSetLogging(logfile,logFunction);
61 	return; }
62 
63 
64 /* smolSetThrowing */
smolSetThrowing(int corethreshold,int libthreshold)65 extern CSTRING void smolSetThrowing(int corethreshold,int libthreshold) {
66 	simSetThrowing(corethreshold);
67 	LibThrowThreshold=libthreshold;
68 	return; }
69 
70 
71 /* smolSetError */
smolSetError(const char * errorfunction,enum ErrorCode errorcode,const char * errorstring,const char * flags)72 extern CSTRING void smolSetError(const char *errorfunction,enum ErrorCode errorcode,const char *errorstring,const char *flags) {
73 	char string[STRCHAR];
74 	int qflag,sflag,wflag;
75 //	int severity;
76 
77 	if(flags) {
78 		qflag=strchr(flags,'q')?1:0;
79 		sflag=strchr(flags,'s')?1:0;
80 		wflag=strchr(flags,'w')?1:0; }
81 	else {
82 		qflag=sflag=wflag=0; }
83 
84 	if(errorcode!=ECsame) {
85 		Liberrorcode=errorcode;
86 		Libwarncode=(errorcode>=ECwarning)?errorcode:ECok;
87 		if(errorstring)
88 			strncpy(Liberrorstring,errorstring,STRCHAR-1);
89 		else Liberrorstring[0]='\0'; }
90 	if(errorfunction)
91 		strncpy(Liberrorfunction,errorfunction,STRCHAR-1);
92 	else Liberrorfunction[0]='\0';
93 
94 //	severity=-(int)errorcode;
95 //??	if(LibThrowThreshold<severity) throw;	//?? This is disabled for now because I can't link libsmoldyn statically if not
96 
97 	if(Libdebugmode && Liberrorfunction[0]!='\0') {
98 		if(Liberrorcode==ECnotify) {
99 			if(!qflag && !sflag)
100 				fprintf(stderr,"Libsmoldyn notification from %s: %s\n",Liberrorfunction,Liberrorstring); }
101 		else if(Liberrorcode==ECwarning) {
102 			if(!sflag && !wflag)
103 				fprintf(stderr,"Libsmoldyn warning in %s: %s\n",Liberrorfunction,Liberrorstring); }
104 		else {
105 			if(!sflag)
106 				fprintf(stderr,"Libsmoldyn '%s' error in %s: %s\n",smolErrorCodeToString(Liberrorcode,string),Liberrorfunction,Liberrorstring); }}
107 	return; }
108 
109 
110 /* smolSetErrorNT */
smolSetErrorNT(const char * errorfunction,enum ErrorCode errorcode,const char * errorstring)111 extern CSTRING void smolSetErrorNT(const char *errorfunction,enum ErrorCode errorcode,const char *errorstring) {
112 	if(errorcode!=ECsame) {
113 		Liberrorcode=errorcode;
114 		Libwarncode=(errorcode>=ECwarning)?errorcode:ECok;
115 		if(errorstring) {
116 			strncpy(Liberrorstring,errorstring,STRCHAR-1);
117 			Liberrorstring[STRCHAR-1] = '\0'; }
118 		else Liberrorstring[0]='\0'; }
119 	if(errorfunction)
120 		strncpy(Liberrorfunction,errorfunction,STRCHAR-1);
121 	else Liberrorfunction[0]='\0';
122 	return; }
123 
124 
125 /* smolGetError */
smolGetError(char * errorfunction,char * errorstring,int clearerror)126 extern CSTRING enum ErrorCode smolGetError(char *errorfunction,char *errorstring,int clearerror) {
127 	enum ErrorCode erc;
128 
129 	erc=Liberrorcode;
130 	if(errorfunction) strcpy(errorfunction,Liberrorfunction);
131 	if(errorstring) strcpy(errorstring,Liberrorstring);
132 	if(clearerror) smolClearError();
133 	return erc; }
134 
135 
136 /* smolClearError */
smolClearError(void)137 extern CSTRING void smolClearError(void) {
138 	Liberrorcode=ECok;
139 	Libwarncode=ECok;
140 	Liberrorfunction[0]='\0';
141 	Liberrorstring[0]='\0';
142 	return; }
143 
144 
145 /* smolSetDebugMode */
smolSetDebugMode(int debugmode)146 extern CSTRING void smolSetDebugMode(int debugmode) {
147 	Libdebugmode=debugmode;
148 	return; }
149 
150 
151 /* smolErrorCodeToString */
smolErrorCodeToString(enum ErrorCode erc,char * string)152 extern CSTRING char *smolErrorCodeToString(enum ErrorCode erc,char *string) {
153 	if(erc==ECok) strcpy(string,"ok");
154 	else if(erc==ECnotify) strcpy(string,"notify");
155 	else if(erc==ECwarning) strcpy(string,"warning");
156 	else if(erc==ECnonexist) strcpy(string,"nonexistant");
157 	else if(erc==ECall) strcpy(string,"all");
158 	else if(erc==ECmissing) strcpy(string,"missing");
159 	else if(erc==ECbounds) strcpy(string,"bounds");
160 	else if(erc==ECsyntax) strcpy(string,"syntax");
161 	else if(erc==ECerror) strcpy(string,"error");
162 	else if(erc==ECmemory) strcpy(string,"memory");
163 	else if(erc==ECbug) strcpy(string,"Smoldyn bug");
164 	else if(erc==ECsame) strcpy(string,"same as before");
165 	else strcpy(string,"undefined");
166 	return string; }
167 
168 
169 /******************************************************************************/
170 /******************************** Sim structure *******************************/
171 /******************************************************************************/
172 
173 /* smolNewSim */
smolNewSim(int dim,double * lowbounds,double * highbounds)174 extern CSTRING simptr smolNewSim(int dim,double *lowbounds,double *highbounds) {
175 	const char *funcname="smolNewSim";
176 	simptr sim;
177 	int d,er;
178 
179 	sim=NULL;
180 	LCHECK(dim>0,funcname,ECbounds,"dim must be >0");
181 	LCHECK(dim<=3,funcname,ECbounds,"dim must be <=3");
182 	LCHECK(lowbounds,funcname,ECmissing,"missing lowbounds");
183 	LCHECK(highbounds,funcname,ECmissing,"missing highbounds");
184 	for(d=0;d<dim;d++)
185 		LCHECK(lowbounds[d]<highbounds[d],funcname,ECbounds,"lowbounds must be < highbounds");
186 
187 	sim=simalloc(NULL);
188 	LCHECK(sim,funcname,ECmemory,"allocating sim");
189 	er=simsetdim(sim,dim);
190 	LCHECK(!er,funcname,ECbug,"simsetdim bug");
191 	for(d=0;d<dim;d++) {
192 		er=walladd(sim,d,0,lowbounds[d],'t');
193 		LCHECK(!er,funcname,ECmemory,"allocating wall");
194 		er=walladd(sim,d,1,highbounds[d],'t');
195 		LCHECK(!er,funcname,ECmemory,"allocating wall"); }
196 
197 	return sim;
198  failure:
199 	if(sim) simfree(sim);
200 	return NULL; }
201 
202 
203 /* smolUpdateSim */
smolUpdateSim(simptr sim)204 extern CSTRING enum ErrorCode smolUpdateSim(simptr sim) {
205 	const char *funcname="smolUpdateSim";
206 	int er;
207 
208 	LCHECK(sim,funcname,ECmissing,"missing sim");
209 	er=simupdate(sim);
210 	LCHECK(!er,funcname,ECerror,ErrorString);	//?? check error handling
211 	return ECok;
212  failure:
213 	return Liberrorcode; }
214 
215 
216 /* smolRunTimeStep */
smolRunTimeStep(simptr sim)217 extern CSTRING enum ErrorCode smolRunTimeStep(simptr sim) {
218 	const char *funcname="smolRunTimeStep";
219 	int er;
220 
221 	LCHECK(sim,funcname,ECmissing,"missing sim");
222 	simsettime(sim,sim->time+sim->dt/2,4);
223 	er=smolsimulate(sim);
224 	LCHECK(er!=1,funcname,ECnotify,"Simulation complete");
225 	LCHECK(er!=2,funcname,ECerror,"Simulation terminated during molecule assignment\n  Out of memory");
226 	LCHECK(er!=3,funcname,ECerror,"Simulation terminated during order 0 reaction\n");
227 	LCHECK(er!=4,funcname,ECerror,"Simulation terminated during order 1 reaction\n");
228 	LCHECK(er!=5,funcname,ECerror,"Simulation terminated during order 2 reaction\n");
229 	LCHECK(er!=6,funcname,ECerror,"Simulation terminated during molecule sorting\n  Out of memory");
230 	LCHECK(er!=7,funcname,ECnotify,"Simulation stopped by a runtime command");
231 	LCHECK(er!=8,funcname,ECerror,"Simulation terminated during simulation state updating\n  Out of memory");
232 	LCHECK(er!=9,funcname,ECerror,"Simulation terminated during diffusion\n  Out of memory");
233 	LCHECK(er!=11,funcname,ECerror,"Simulation terminated during filament dynamics");
234 	LCHECK(er!=12,funcname,ECerror,"Simulation terminated during lattice simulation");
235 	LCHECK(er!=13,funcname,ECerror,"Simulation terminated during reaction network expansion");
236 	return Libwarncode;
237  failure:
238 	return Liberrorcode; }
239 
240 
241 /* smolRunSim */
smolRunSim(simptr sim)242 extern CSTRING enum ErrorCode smolRunSim(simptr sim) {
243 	const char *funcname="smolRunSim";
244 	int er;
245 
246 	LCHECK(sim,funcname,ECmissing,"missing sim");
247 	er=smolOpenOutputFiles(sim, true);
248 	LCHECK(!er,funcname,ECerror,"Cannot open output files for writing");
249 
250 	if(sim->graphss && sim->graphss->graphics>0 && !strchr(sim->flags,'t'))
251 		smolsimulategl(sim);
252 	else {
253 		er=smolsimulate(sim);
254 		LCHECK(er!=1,funcname,ECnotify,"Simulation complete");
255 		LCHECK(er!=2,funcname,ECerror,"Simulation terminated during molecule assignment\n  Out of memory");
256 		LCHECK(er!=3,funcname,ECerror,"Simulation terminated during order 0 reaction\n  Not enough molecules allocated");
257 		LCHECK(er!=4,funcname,ECerror,"Simulation terminated during order 1 reaction\n  Not enough molecules allocated");
258 		LCHECK(er!=5,funcname,ECerror,"Simulation terminated during order 2 reaction\n  Not enough molecules allocated");
259 		LCHECK(er!=6,funcname,ECerror,"Simulation terminated during molecule sorting\n  Out of memory");
260 		LCHECK(er!=7,funcname,ECnotify,"Simulation stopped by a runtime command");
261 		LCHECK(er!=8,funcname,ECerror,"Simulation terminated during simulation state updating\n  Out of memory");
262 		LCHECK(er!=9,funcname,ECerror,"Simulation terminated during diffusion\n  Out of memory"); }
263 
264         // FIXME. If run() is called again, previous Liberrorcode does not
265         // reset to ECok but remain stuck to ECnotify.
266         if(Libwarncode == ECnotify)
267             Libwarncode = ECok;
268         return Libwarncode;
269  failure:
270 	return Liberrorcode; }
271 
272 
273 /* smolRunSimUntil */
smolRunSimUntil(simptr sim,double breaktime)274 extern CSTRING enum ErrorCode smolRunSimUntil(simptr sim,double breaktime) {
275 	const char *funcname="smolRunSimUntil";
276 	double stoptime;
277 
278 	LCHECK(sim,funcname,ECmissing,"missing sim");
279 	stoptime=sim->tmax;
280 	simsettime(sim,breaktime,4);
281 	smolRunSim(sim);
282 	simsettime(sim,stoptime,4);
283 	return Libwarncode;
284  failure:
285 	return Liberrorcode; }
286 
287 
288 /* smolFreeSim */
smolFreeSim(simptr sim)289 extern CSTRING enum ErrorCode smolFreeSim(simptr sim) {
290 	simfree(sim);
291 	return ECok; }
292 
293 
294 /* smolDisplaySim */
smolDisplaySim(simptr sim)295 extern CSTRING enum ErrorCode smolDisplaySim(simptr sim) {
296 	simsystemoutput(sim);
297 	checksimparams(sim);
298 	return ECok; }
299 
300 
301 /******************************************************************************/
302 /************************** Read configuration file ***************************/
303 /******************************************************************************/
304 
305 
306 /* smolPrepareSimFromFile */
smolPrepareSimFromFile(const char * filepath,const char * filename,const char * flags)307 extern CSTRING simptr smolPrepareSimFromFile(const char *filepath,const char *filename,const char *flags) {
308 	const char *funcname="smolPrepareSimFromFile";
309 	int er;
310 	char emptystring[STRCHAR];
311 	simptr sim;
312 
313 	sim=NULL;
314 	LCHECK(filename,funcname,ECmissing,"missing filename");
315 
316 	emptystring[0]='\0';
317 	if(!filepath) filepath=emptystring;
318 	if(!flags) flags=emptystring;
319 #ifdef OPTION_VCELL
320 	er=simInitAndLoad(filepath,filename,&sim,flags,new SimpleValueProviderFactory(),new SimpleMesh());
321 #else
322 	er=simInitAndLoad(filepath,filename,&sim,flags);
323 #endif
324 	LCHECKNT(!er,funcname,ECerror,ErrorLineAndString);
325 	er=simUpdateAndDisplay(sim);
326 	LCHECK(!er,funcname,ECerror,"Failed to update simulation");
327 	return sim;
328  failure:
329 	simfree(sim);
330 	return NULL; }
331 
332 
333 /* smolLoadSimFromFile */
smolLoadSimFromFile(const char * filepath,const char * filename,simptr * simpointer,const char * flags)334 extern CSTRING enum ErrorCode smolLoadSimFromFile(const char *filepath,const char *filename,simptr *simpointer,const char *flags) {
335 	const char *funcname="smolLoadSimFromFile";
336 	int er;
337 	char emptystring[STRCHAR];
338 	simptr sim;
339 
340 	sim=NULL;
341 	LCHECK(filename,funcname,ECmissing,"missing filename");
342 	LCHECK(simpointer,funcname,ECmissing,"missing simpointer");
343 
344 	emptystring[0]='\0';
345 	if(!filepath) filepath=emptystring;
346 	if(!flags) flags=emptystring;
347 
348 	sim=*simpointer;
349 	if(!sim) {
350 		sim=simalloc(filepath);
351 		LCHECK(sim,funcname,ECmemory,"allocating sim"); }
352 	er=loadsim(sim,filepath,filename,flags);
353 	LCHECKNT(!er,funcname,ECerror,ErrorLineAndString);
354 
355 	*simpointer=sim;
356 	return ECok;
357  failure:
358 	return Liberrorcode; }
359 
360 
361 /* smolReadConfigString */
smolReadConfigString(simptr sim,const char * statement,char * parameters)362 extern CSTRING enum ErrorCode smolReadConfigString(simptr sim,const char *statement,char *parameters) {
363 	const char *funcname="smolReadConfigString";
364 	int er;
365 
366 	LCHECK(sim,funcname,ECmissing,"missing sim");
367 	LCHECK(statement,funcname,ECmissing,"missing statement");
368 	er=simreadstring(sim,NULL,statement,parameters);
369 	LCHECK(!er,funcname,ECerror,"Error in configuration string");
370 
371 	return ECok;
372  failure:
373 	return Liberrorcode; }
374 
375 
376 /******************************************************************************/
377 /***************************** Simulation settings ****************************/
378 /******************************************************************************/
379 
380 
381 /* smolSetSimFlags */
smolSetSimFlags(simptr sim,const char * flags)382 extern CSTRING enum ErrorCode smolSetSimFlags(simptr sim,const char *flags) {
383 	const char *funcname="smolSetSimFlags";
384 
385 	LCHECK(sim,funcname,ECmissing,"missing sim");
386 	LCHECK(flags,funcname,ECmissing,"missing flags");
387 	strncpy(sim->flags,flags,STRCHAR);
388 	return ECok;
389  failure:
390 	return Liberrorcode; }
391 
392 
393 /* smolSetSimTimes */
smolSetSimTimes(simptr sim,double timestart,double timestop,double timestep)394 extern CSTRING enum ErrorCode smolSetSimTimes(simptr sim,double timestart,double timestop,double timestep) {
395 	const char *funcname="smolSetSimTimes";
396 
397 	LCHECK(sim,funcname,ECmissing,"missing sim");
398 	LCHECK(timestep>0,funcname,ECbounds,"timestep value");
399 	simsettime(sim,timestart,0);
400 	simsettime(sim,timestart,1);
401 	simsettime(sim,timestop,2);
402 	simsettime(sim,timestep,3);
403 	return ECok;
404  failure:
405 	return Liberrorcode; }
406 
407 
408 /* smolSetTimeStart */
smolSetTimeStart(simptr sim,double timestart)409 extern CSTRING enum ErrorCode smolSetTimeStart(simptr sim,double timestart) {
410 	const char *funcname="smolSetTimeStart";
411 
412 	LCHECK(sim,funcname,ECmissing,"missing sim");
413 	simsettime(sim,timestart,1);
414 	return ECok;
415  failure:
416 	return Liberrorcode; }
417 
418 
419 /* smolSetTimeStop */
smolSetTimeStop(simptr sim,double timestop)420 extern CSTRING enum ErrorCode smolSetTimeStop(simptr sim,double timestop) {
421 	const char *funcname="smolSetTimeStop";
422 
423 	LCHECK(sim,funcname,ECmissing,"missing sim");
424 	simsettime(sim,timestop,2);
425 	return ECok;
426  failure:
427 	return Liberrorcode; }
428 
429 
430 /* smolSetTimeNow */
smolSetTimeNow(simptr sim,double timenow)431 extern CSTRING enum ErrorCode smolSetTimeNow(simptr sim,double timenow) {
432 	const char *funcname="smolSetTimeNow";
433 
434 	LCHECK(sim,funcname,ECmissing,"missing sim");
435 	simsettime(sim,timenow,0);
436 	return ECok;
437  failure:
438 	return Liberrorcode; }
439 
440 
441 /* smolSetTimeStep */
smolSetTimeStep(simptr sim,double timestep)442 extern CSTRING enum ErrorCode smolSetTimeStep(simptr sim,double timestep) {
443 	const char *funcname="smolSetTimeStep";
444 
445 	LCHECK(sim,funcname,ECmissing,"missing sim");
446 	LCHECK(timestep>0,funcname,ECbounds,"timestep is not > 0");
447 	simsettime(sim,timestep,3);
448 	return ECok;
449  failure:
450 	return Liberrorcode; }
451 
452 
453 /* smolSetRandomSeed */
smolSetRandomSeed(simptr sim,long int seed)454 extern CSTRING enum ErrorCode smolSetRandomSeed(simptr sim,long int seed) {
455 	const char *funcname="smolSetRandomSeed";
456 
457 	LCHECK(sim,funcname,ECmissing,"missing sim");
458 	Simsetrandseed(sim,seed);
459 	return ECok;
460  failure:
461 	return Liberrorcode; }
462 
463 
464 /* smolSetPartitions */
smolSetPartitions(simptr sim,const char * method,double value)465 extern CSTRING enum ErrorCode smolSetPartitions(simptr sim,const char *method,double value) {
466 	const char *funcname="smolSetPartitions";
467 	int er;
468 
469 	LCHECK(sim,funcname,ECmissing,"missing sim");
470 	LCHECK(method,funcname,ECmissing,"missing method string");
471 	LCHECK(value>0,funcname,ECbounds,"value needs to be > 0");
472 	er=boxsetsize(sim,method,value);
473 	LCHECK(er!=1,funcname,ECmemory,"out of memory");
474 	LCHECK(er!=2,funcname,ECsyntax,"method is not recognized");
475 	return ECok;
476  failure:
477 	return Liberrorcode; }
478 
479 
480 /******************************************************************************/
481 /********************************** Graphics **********************************/
482 /******************************************************************************/
483 
484 /* smolSetGraphicsParams */
smolSetGraphicsParams(simptr sim,const char * method,int timesteps,int delay)485 extern CSTRING enum ErrorCode smolSetGraphicsParams(simptr sim,const char *method,int timesteps,int delay) {
486 	const char *funcname="smolSetGraphicsParams";
487 	int er;
488 
489 	LCHECK(sim,funcname,ECmissing,"missing sim");
490 	er=graphicsenablegraphics(sim,method);
491 	LCHECK(er!=1,funcname,ECmemory,"out of memory");
492 	LCHECK(er!=2,funcname,ECmissing,"missing sim");
493 	LCHECK(er!=3,funcname,ECsyntax,"graphics method not recognized");
494 	if(timesteps>0) {
495 		er=graphicssetiter(sim,timesteps);
496 		LCHECK(er!=1,funcname,ECmemory,"out of memory enabling graphics");
497 		LCHECK(er!=2,funcname,ECbug,"BUG: missing parameter");
498 		LCHECK(er!=3,funcname,ECbug,"BUG: timesteps needs to be >=1"); }
499 	if(delay>=0) {
500 		er=graphicssetdelay(sim,delay);
501 		LCHECK(er!=1,funcname,ECmemory,"out of memory enabling graphics");
502 		LCHECK(er!=2,funcname,ECbug,"BUG: missing parameter");
503 		LCHECK(er!=3,funcname,ECbug,"BUG: delay needs to be >=0"); }
504 	return ECok;
505  failure:
506 	return Liberrorcode; }
507 
508 
509 /* smolSetTiffParams */
smolSetTiffParams(simptr sim,int timesteps,const char * tiffname,int lowcount,int highcount)510 extern CSTRING enum ErrorCode smolSetTiffParams(simptr sim,int timesteps,const char *tiffname,int lowcount,int highcount) {
511 	const char *funcname="smolSetTiffParams";
512 	char nm1[STRCHAR];
513 	int er;
514 
515 	LCHECK(sim,funcname,ECmissing,"missing sim");
516 	if(timesteps>0) {
517 		er=graphicssettiffiter(sim,timesteps);
518 		LCHECK(er!=1,funcname,ECmemory,"out of memory enabling graphics");
519 		LCHECK(er!=2,funcname,ECbug,"BUG: missing parameter");
520 		LCHECK(er!=3,funcname,ECbug,"BUG: timesteps needs to be >=1"); }
521 	if(tiffname) {
522 		strcpy(nm1,sim->filepath);
523 		strncat(nm1,tiffname,STRCHAR-1-strlen(nm1));
524 		gl2SetOptionStr("TiffName",nm1); }
525 	if(lowcount>=0) {
526 		gl2SetOptionInt("TiffNumber",lowcount); }
527 	if(highcount>=0) {
528 		gl2SetOptionInt("TiffNumMax",highcount); }
529 	return ECok;
530  failure:
531 	return Liberrorcode; }
532 
533 
534 /* smolSetLightParams */
smolSetLightParams(simptr sim,int lightindex,double * ambient,double * diffuse,double * specular,double * position)535 extern CSTRING enum ErrorCode smolSetLightParams(simptr sim,int lightindex,double *ambient,double *diffuse,double *specular,double *position) {
536 	const char *funcname="smolSetLightParams";
537 	int c,er;
538 
539 	LCHECK(sim,funcname,ECmissing,"missing sim");
540 	LCHECK(lightindex>=-1 && lightindex<MAXLIGHTS,funcname,ECbounds,"lightindex out of bounds");
541 	LCHECK(lightindex>=0 || (!diffuse && !specular && !position),funcname,ECsyntax,"can only set ambient for global light");
542 
543 	if(ambient) {
544 		for(c=0;c<4;c++)
545 			LCHECK(ambient[c]>=0 && ambient[c]<=1,funcname,ECbounds,"ambient light value out of bounds");
546 		er=graphicssetlight(sim,NULL,lightindex,LPambient,ambient);
547 		LCHECK(!er,funcname,ECmemory,"out of memory enabling graphics"); }
548 	if(diffuse) {
549 		for(c=0;c<4;c++)
550 			LCHECK(diffuse[c]>=0 && diffuse[c]<=1,funcname,ECbounds,"diffuse light value out of bounds");
551 		er=graphicssetlight(sim,NULL,lightindex,LPdiffuse,diffuse);
552 		LCHECK(!er,funcname,ECmemory,"out of memory enabling graphics"); }
553 	if(specular) {
554 		for(c=0;c<4;c++)
555 			LCHECK(specular[c]>=0 && specular[c]<=1,funcname,ECbounds,"specular light value out of bounds");
556 		er=graphicssetlight(sim,NULL,lightindex,LPspecular,specular);
557 		LCHECK(!er,funcname,ECmemory,"out of memory enabling graphics"); }
558 	if(position) {
559 		er=graphicssetlight(sim,NULL,lightindex,LPposition,position);
560 		LCHECK(!er,funcname,ECmemory,"out of memory enabling graphics"); }
561 
562 	return ECok;
563  failure:
564 	return Liberrorcode; }
565 
566 
567 /* smolSetBackgroundStyle */
smolSetBackgroundStyle(simptr sim,double * color)568 extern CSTRING enum ErrorCode smolSetBackgroundStyle(simptr sim,double *color) {
569 	const char *funcname="smolSetBackgroundStyle";
570 	int c,er;
571 
572 	LCHECK(sim,funcname,ECmissing,"missing sim");
573 	if(color) {
574 		for(c=0;c<4;c++)
575 			LCHECK(color[c]>=0 && color[c]<=1,funcname,ECbounds,"color value out of bounds");
576 		er=graphicssetbackcolor(sim,color);
577 		LCHECK(!er,funcname,ECmemory,"out of memory enabling graphics"); }
578 	return ECok;
579  failure:
580 	return Liberrorcode; }
581 
582 
583 /* smolSetFrameStyle */
smolSetFrameStyle(simptr sim,double thickness,double * color)584 extern CSTRING enum ErrorCode smolSetFrameStyle(simptr sim,double thickness,double *color) {
585 	const char *funcname="smolSetFrameStyle";
586 	int c,er;
587 
588 	LCHECK(sim,funcname,ECmissing,"missing sim");
589 	if(thickness>=0) {
590 		er=graphicssetframethickness(sim,thickness);
591 		LCHECK(!er,funcname,ECmemory,"out of memory enabling graphics"); }
592 	if(color) {
593 		for(c=0;c<4;c++)
594 			LCHECK(color[c]>=0 && color[c]<=1,funcname,ECbounds,"color value out of bounds");
595 		er=graphicssetframecolor(sim,color);
596 		LCHECK(!er,funcname,ECmemory,"out of memory enabling graphics"); }
597 	return ECok;
598  failure:
599 	return Liberrorcode; }
600 
601 
602 /* smolSetGridStyle */
smolSetGridStyle(simptr sim,double thickness,double * color)603 extern CSTRING enum ErrorCode smolSetGridStyle(simptr sim,double thickness,double *color) {
604 	const char *funcname="smolSetGridStyle";
605 	int c,er;
606 
607 	LCHECK(sim,funcname,ECmissing,"missing sim");
608 	if(thickness>=0) {
609 		er=graphicssetgridthickness(sim,thickness);
610 		LCHECK(!er,funcname,ECmemory,"out of memory enabling graphics"); }
611 	if(color) {
612 		for(c=0;c<4;c++)
613 			LCHECK(color[c]>=0 && color[c]<=1,funcname,ECbounds,"color value out of bounds");
614 		er=graphicssetgridcolor(sim,color);
615 		LCHECK(!er,funcname,ECmemory,"out of memory enabling graphics"); }
616 	return ECok;
617  failure:
618 	return Liberrorcode; }
619 
620 
621 /* smolSetTextStyle */
smolSetTextStyle(simptr sim,double * color)622 extern CSTRING enum ErrorCode smolSetTextStyle(simptr sim,double *color) {
623 	const char *funcname="smolSetTextStyle";
624 	int c,er;
625 
626 	LCHECK(sim,funcname,ECmissing,"missing sim");
627 	if(color) {
628 		for(c=0;c<4;c++)
629 			LCHECK(color[c]>=0 && color[c]<=1,funcname,ECbounds,"color value out of bounds");
630 		er=graphicssettextcolor(sim,color);
631 		LCHECK(!er,funcname,ECmemory,"out of memory enabling graphics"); }
632 	return ECok;
633  failure:
634 	return Liberrorcode; }
635 
636 
637 /* smolAddTextDisplay */
smolAddTextDisplay(simptr sim,char * item)638 extern CSTRING enum ErrorCode smolAddTextDisplay(simptr sim,char *item) {
639 	const char *funcname="smolAddTextDisplay";
640 	int er;
641 
642 	LCHECK(sim,funcname,ECmissing,"missing sim");
643 	er=graphicssettextitem(sim,item);
644 	LCHECK(er!=1,funcname,ECmemory,"out of memory adding text display item");
645 	LCHECK(er!=2,funcname,ECsyntax,"listed item is not recognized or not supported");
646 	LCHECK(er!=3,funcname,ECwarning,"text display item was already listed");
647 	return Libwarncode;
648  failure:
649 	return Liberrorcode; }
650 
651 
652 /******************************************************************************/
653 /***************************** Runtime commands *******************************/
654 /******************************************************************************/
655 
656 /* smolSetOutputPath */
smolSetOutputPath(simptr sim,const char * path)657 extern CSTRING enum ErrorCode smolSetOutputPath(simptr sim,const char *path) {
658 	const char *funcname="smolSetOutputPath";
659 	int er;
660 
661 	LCHECK(sim,funcname,ECmissing,"missing sim");
662 	LCHECK(path,funcname,ECmissing,"missing path");
663 	er=scmdsetfroot(sim->cmds,path);
664 	LCHECK(!er,funcname,ECbug,"scmdsetfroot bug");
665 	return ECok;
666  failure:
667 	return Liberrorcode; }
668 
669 
670 /* smolAddOutputFile */
smolAddOutputFile(simptr sim,char * filename,int suffix,int append)671 extern CSTRING enum ErrorCode smolAddOutputFile(simptr sim,char *filename,int suffix,int append) {
672 	const char *funcname="smolAddOutputFile";
673 	int er;
674 
675 	LCHECK(sim,funcname,ECmissing,"missing sim");
676 	LCHECK(filename,funcname,ECmissing,"missing filename");
677 	LCHECK(!strchr(filename,' '),funcname,ECwarning,"only first word of filename is used");
678 	er=scmdsetfnames(sim->cmds,filename,append);
679 	LCHECK(!er,funcname,ECmemory,"allocating filename");
680 	if(suffix>=0) {
681 		er=scmdsetfsuffix(sim->cmds,filename,suffix);
682 		LCHECK(!er,funcname,ECbug,"scmdsetfsuffix bug"); }
683 
684 	return Libwarncode;
685  failure:
686 	return Liberrorcode; }
687 
688 
689 /* smolAddOutputData */
smolAddOutputData(simptr sim,char * dataname)690 extern CSTRING enum ErrorCode smolAddOutputData(simptr sim,char *dataname) {
691 	const char *funcname="smolAddOutputData";
692 	int er;
693 
694 	LCHECK(sim,funcname,ECmissing,"missing sim");
695 	LCHECK(dataname,funcname,ECmissing,"missing dataname");
696 	LCHECK(!strchr(dataname,' '),funcname,ECwarning,"only first word of dataname is used");
697 	er=scmdsetdnames(sim->cmds,dataname);
698 	LCHECK(!er,funcname,ECmemory,"allocating dataname");
699 	return Libwarncode;
700  failure:
701 	return Liberrorcode; }
702 
703 
704 /* smolOpenOutputFiles */
smolOpenOutputFiles(simptr sim,int overwrite=0)705 enum ErrorCode smolOpenOutputFiles(simptr sim, int overwrite = 0)
706 {
707     const char *funcname = "smolOpenOutputFiles";
708     int err              = scmdopenfiles(sim->cmds, overwrite);
709     LCHECK(!err, funcname, ECerror, "Unable (or forbidden) to open output files for writing");
710 
711     return Libwarncode;
712 failure:
713     return Liberrorcode;
714 }
715 
716 /* smolAddCommand */
smolAddCommand(simptr sim,char type,double on,double off,double step,double multiplier,const char * commandstring)717 extern CSTRING enum ErrorCode smolAddCommand(simptr sim,char type,double on,double off,double step,double multiplier,const char *commandstring) {
718 	const char *funcname="smolSetCommand";
719 	int er;
720 
721 	LCHECK(sim,funcname,ECmissing,"missing sim");
722 	er=scmdaddcommand(sim->cmds,type,on,off,step,multiplier,commandstring);
723 	LCHECK(er!=1,funcname,ECmemory,"out of memory creating command");
724 	LCHECK(er!=2,funcname,ECbug,"missing sim->cmds");
725 	LCHECK(er!=3,funcname,ECsyntax,"missing command string");
726 	return ECok;
727  failure:
728 	return Liberrorcode; }
729 
730 
731 /* smolAddCommandFromString */
smolAddCommandFromString(simptr sim,char * string)732 extern CSTRING enum ErrorCode smolAddCommandFromString(simptr sim,char *string) {
733 	const char *funcname="smolSetCommandFromString";
734 	int er;
735 
736 	LCHECK(sim,funcname,ECmissing,"missing sim");
737 	LCHECK(string,funcname,ECmissing,"missing string");
738 	er=scmdstr2cmd(sim->cmds,string,NULL,NULL,0);
739 	LCHECK(er!=1,funcname,ECmemory,"out of memory in cmd");
740 	LCHECK(er!=2,funcname,ECbug,"BUG: no command superstructure for cmd");
741 	LCHECK(er!=3,funcname,ECsyntax,"cmd format: type [on off dt] string");
742 	LCHECK(er!=5,funcname,ECbounds,"cmd time step needs to be >0");
743 	LCHECK(er!=8,funcname,ECbounds,"cmd time multiplier needs to be >1");
744 	return ECok;
745  failure:
746 	return Liberrorcode; }
747 
748 
749 /* smolGetOutputData */
smolGetOutputData(simptr sim,char * dataname,int * nrow,int * ncol,double ** array,int erase)750 extern CSTRING enum ErrorCode smolGetOutputData(simptr sim,char *dataname,int *nrow,int *ncol,double **array,int erase) {
751 	const char *funcname="smolGetOutputData";
752 	int did,i,j;
753 	listptrdd list;
754 	double *datacopy;
755 
756 	LCHECK(sim,funcname,ECmissing,"missing sim");
757 	LCHECK(dataname,funcname,ECmissing,"missing dataname");
758 	LCHECK(nrow && ncol && array,funcname,ECmissing,"missing pointer for returned data");
759 	LCHECK(sim->cmds && sim->cmds->ndata>0,funcname,ECerror,"no data files in the sim");
760 	did=stringfind(sim->cmds->dname,sim->cmds->ndata,dataname);
761 	LCHECK(did>=0,funcname,ECerror,"no data file of the requested name");
762 	list=sim->cmds->data[did];
763 
764     datacopy=(double*) calloc(list->nrow*list->ncol,sizeof(double));
765     LCHECK(datacopy,funcname,ECmemory,"out of memory");
766     for(i=0;i<list->nrow;i++)
767         for(j=0;j<list->ncol;j++)
768             datacopy[i*list->ncol+j]=list->data[i*list->maxcol+j];
769     *nrow=list->nrow;
770     *ncol=list->ncol;
771     *array=datacopy;
772 	if(erase) ListClearDD(list);
773 
774 	return ECok;
775  failure:
776 	return Liberrorcode; }
777 
778 
smolRunCommand(simptr sim,const char * commandstring)779 extern CSTRING enum ErrorCode smolRunCommand(simptr sim,const char *commandstring) {
780 	const char *funcname="smolRunCommand";
781 	char stringcopy[STRCHAR];
782 	cmdptr cmd;
783 	enum CMDcode cmdcode;
784 
785 	LCHECK(sim,funcname,ECmissing,"missing sim");
786 	LCHECK(commandstring,funcname,ECmissing,"missing command string");
787 	strncpy(stringcopy,commandstring,STRCHAR-1);
788 	cmd=scmdalloc();
789 	LCHECK(cmd,funcname,ECmemory,"failed to create a new command structure");
790 	strcpy(cmd->str,stringcopy);
791 	cmdcode=docommand((void*)sim,cmd,stringcopy);
792 	LCHECK(cmdcode==CMDok,funcname,ECwarning,cmd->erstr);
793 	scmdfree(cmd);
794 	return ECok;
795  failure:
796 	return Liberrorcode; }
797 
798 
799 /******************************************************************************/
800 /********************************* Molecules **********************************/
801 /******************************************************************************/
802 
803 /* smolAddSpecies */
smolAddSpecies(simptr sim,const char * species,const char * mollist)804 extern CSTRING enum ErrorCode smolAddSpecies(simptr sim,const char *species,const char *mollist) {
805 	const char *funcname="smolAddSpecies";
806 	int i,ll;
807 
808 	LCHECK(sim,funcname,ECmissing,"missing sim");
809 	LCHECK(species,funcname,ECmissing,"missing species");
810 	if(mollist && mollist[0]!='\0') {
811 		ll=smolGetMolListIndexNT(sim,mollist);
812 		LCHECK(ll>=0,funcname,ECsame,NULL);
813 		LCHECK(sim->mols->listtype[ll]==MLTsystem,funcname,ECsyntax,"mollist is not a system list"); }
814 	else ll=-1;
815 	i=moladdspecies(sim,species);
816 	LCHECK(i!=-1,funcname,ECbug,"out of memory");
817 	LCHECK(i!=-2,funcname,ECbug,"add species bug");
818 	LCHECK(i!=-3,funcname,ECbug,"more species are entered than are automatically allocated");
819 	LCHECK(i!=-4,funcname,ECsyntax,"'empty' is not a permitted species name");
820 	LCHECK(i!=-5,funcname,ECwarning,"this species has already been declared");
821 	LCHECK(i!=-6,funcname,ECsyntax,"'?' and '*' are not allowed in species names");
822 	if(mollist && mollist[0]!='\0')
823 		molsetlistlookup(sim,i,NULL,MSall,ll);
824 	return Libwarncode;
825  failure:
826 	return Liberrorcode; }
827 
828 
829 /* smolGetSpeciesIndex */
smolGetSpeciesIndex(simptr sim,const char * species)830 extern CSTRING int smolGetSpeciesIndex(simptr sim,const char *species) {
831 	const char *funcname="smolGetSpeciesIndex";
832 	int i;
833 
834 	LCHECK(sim,funcname,ECmissing,"missing sim");
835 	LCHECK(species,funcname,ECmissing,"missing species name");
836 	LCHECK(sim->mols,funcname,ECnonexist,"no species defined");
837 	LCHECK(strcmp(species,"all"),funcname,ECall,"species is 'all'");
838 	i=stringfind(sim->mols->spname,sim->mols->nspecies,species);
839 	if(i<=0) {
840 		char buffer[STRCHAR];
841 		snprintf(buffer,STRCHAR,"species '%s' not found",species);
842 		LCHECK(0,funcname,ECnonexist,buffer); }
843 	return i;
844  failure:
845 	return (int)Liberrorcode; }
846 
847 
848 /* smolGetSpeciesIndexNT */
smolGetSpeciesIndexNT(simptr sim,const char * species)849 extern CSTRING int smolGetSpeciesIndexNT(simptr sim,const char *species) {
850 	const char *funcname="smolGetSpeciesIndexNT";
851 	int i;
852 
853 	LCHECKNT(sim,funcname,ECmissing,"missing sim");
854 	LCHECKNT(species,funcname,ECmissing,"missing species name");
855 	LCHECKNT(sim->mols,funcname,ECnonexist,"no species defined");
856 	LCHECKNT(strcmp(species,"all"),funcname,ECall,"species cannot be 'all'");
857 	i=stringfind(sim->mols->spname,sim->mols->nspecies,species);
858 	if(i<=0) {
859 		char buffer[STRCHAR];
860 		snprintf(buffer,STRCHAR,"species '%s' not found",species);
861 		LCHECKNT(0,funcname,ECnonexist,buffer); }
862 	return i;
863  failure:
864 	return (int)Liberrorcode; }
865 
866 
867 /* smolGetSpeciesName */
smolGetSpeciesName(simptr sim,int speciesindex,char * species)868 extern CSTRING void smolGetSpeciesName(simptr sim,int speciesindex,char *species) {
869 	const char *funcname="smolGetSpeciesName";
870 
871 	LCHECK(sim,funcname,ECmissing,"missing sim");
872 	LCHECK(sim->mols,funcname,ECnonexist,"no species defined");
873 	LCHECK(speciesindex>=0,funcname,ECbounds,"speciesindex < 0");
874 	LCHECK(speciesindex<sim->mols->nspecies,funcname,ECnonexist,"species doesn't exist");
875 	LCHECK(species,funcname,ECmissing,"missing species");
876 	strcpy(species,sim->mols->spname[speciesindex]);
877  failure:
878 	return; }
879 
880 
881 /* smolGetSpecies */
smolGetSpecies(simptr sim,int speciesindex,char * speciesname,double * difc,double ** color,double * displaysize,char ** listname)882 extern CSTRING int smolGetSpecies(simptr sim,int speciesindex,char *speciesname,double *difc,double **color,double *displaysize,char **listname) {
883 	const char *funcname="smolGetSpecies";
884 	int i=0;
885 	enum MolecState ms;
886 
887 	LCHECK(sim,funcname,ECmissing,"missing sim");
888 	LCHECK(sim->mols,funcname,ECnonexist,"no species defined");
889 	if(speciesindex>=0) {
890 		LCHECK(speciesindex<sim->mols->nspecies,funcname,ECnonexist,"species doesn't exist");
891 		if(speciesname) strcpy(speciesname,sim->mols->spname[speciesindex]); }
892 	else {
893 		LCHECK(speciesname,funcname,ECmissing,"missing species name");
894 		LCHECK(strcmp(speciesname,"all"),funcname,ECall,"species is 'all'");
895 		i=stringfind(sim->mols->spname,sim->mols->nspecies,speciesname);
896 		if(i<=0) {
897 			char buffer[STRCHAR];
898 			snprintf(buffer,STRCHAR,"species '%s' not found",speciesname);
899 			LCHECK(0,funcname,ECnonexist,buffer); }}
900 	for(ms=(enum MolecState)0;ms<(enum MolecState)MSMAX;ms=(enum MolecState)(ms+1)) {
901 		if(difc) difc[ms]=sim->mols->difc[i][ms];
902 		if(color) {
903 			color[ms][0]=sim->mols->color[i][ms][0];
904 			color[ms][1]=sim->mols->color[i][ms][1];
905 			color[ms][2]=sim->mols->color[i][ms][2];
906 			color[ms][3]=sim->mols->color[i][ms][3]; }
907 		if(displaysize) displaysize[ms]=sim->mols->display[i][ms];
908 		if(listname) strcpy(listname[ms],sim->mols->listname[sim->mols->listlookup[i][ms]]); }
909 	return i;
910  failure:
911 	return (int)Liberrorcode; }
912 
913 
914 /* smolSetSpeciesMobility */
smolSetSpeciesMobility(simptr sim,const char * species,enum MolecState state,double difc,double * drift,double * difmatrix)915 extern CSTRING enum ErrorCode smolSetSpeciesMobility(simptr sim,const char *species,enum MolecState state,double difc,double *drift,double *difmatrix) {
916 	const char *funcname="smolSetSpeciesMobility";
917 	int i,er,isall,ilow,ihigh;
918 
919 	LCHECK(sim,funcname,ECmissing,"missing sim");
920 	LCHECK(sim->mols,funcname,ECnonexist,"no species defined");
921 	isall=0;
922 	i=smolGetSpeciesIndexNT(sim,species);
923 	if(i==(int)ECall) {smolClearError();isall=1;}
924 	else LCHECK(i>0,funcname,ECsame,NULL);
925 	LCHECK((state>=0 && state<MSMAX) || state==MSall,funcname,ECsyntax,"invalid state");
926 
927 	if(isall) {
928 		ilow=1;
929 		ihigh=sim->mols->nspecies; }
930 	else {
931 		ilow=i;
932 		ihigh=i+1; }
933 
934 	for(i=ilow;i<ihigh;i++) {
935 		if(difc>=0) {
936 			molsetdifc(sim,i,NULL,state,difc); }
937 		if(drift) {
938 			er=molsetdrift(sim,i,NULL,state,drift);
939 			LCHECK(!er,funcname,ECmemory,"allocating drift"); }
940 		if(difmatrix) {
941 			er=molsetdifm(sim,i,NULL,state,difmatrix);
942 			LCHECK(!er,funcname,ECmemory,"allocating difmatrix"); }}
943 
944 	return ECok;
945  failure:
946 	return Liberrorcode; }
947 
948 
949 //?? need to add function for smolSetSpeciesSurfaceDrift
950 
951 
952 /* smolAddMolList */
smolAddMolList(simptr sim,const char * mollist)953 extern CSTRING enum ErrorCode smolAddMolList(simptr sim,const char *mollist) {
954 	const char *funcname="smolAddMolList";
955 	int ll;
956 
957 	LCHECK(sim,funcname,ECmissing,"missing sim");
958 	LCHECK(mollist,funcname,ECmissing,"missing mollist");
959 	ll=addmollist(sim,mollist,MLTsystem);
960 	LCHECK(ll!=-1,funcname,ECmemory,"out of memory");
961 	LCHECK(ll!=-2,funcname,ECwarning,"molecule list name has already been used");
962 	LCHECK(ll!=-3,funcname,ECbug,"illegal addmollist inputs");
963 	return Libwarncode;
964  failure:
965 	return Liberrorcode; }
966 
967 
968 /* smolGetMolListIndex */
smolGetMolListIndex(simptr sim,const char * mollist)969 extern CSTRING int smolGetMolListIndex(simptr sim,const char *mollist) {
970 	const char *funcname="smolGetMolListIndex";
971 	int ll;
972 
973 	LCHECK(sim,funcname,ECmissing,"missing sim");
974 	LCHECK(mollist,funcname,ECmissing,"missing mollist");
975 	LCHECK(sim->mols,funcname,ECnonexist,"no molecule lists defined");
976 	LCHECK(strcmp(mollist,"all"),funcname,ECall,"molecule list is 'all'");
977 	ll=stringfind(sim->mols->listname,sim->mols->nlist,mollist);
978 	LCHECK(ll>=0,funcname,ECnonexist,"list name not recognized");
979 	return ll;
980  failure:
981 	return (int)Liberrorcode; }
982 
983 
984 /* smolGetMolListIndexNT */
smolGetMolListIndexNT(simptr sim,const char * mollist)985 extern CSTRING int smolGetMolListIndexNT(simptr sim,const char *mollist) {
986 	const char *funcname="smolGetMolListIndexNT";
987 	int ll;
988 
989 	LCHECKNT(sim,funcname,ECmissing,"missing sim");
990 	LCHECKNT(mollist,funcname,ECmissing,"missing mollist");
991 	LCHECKNT(sim->mols,funcname,ECnonexist,"no molecule lists defined");
992 	LCHECKNT(strcmp(mollist,"all"),funcname,ECall,"molecule list cannot be 'all'");
993 	ll=stringfind(sim->mols->listname,sim->mols->nlist,mollist);
994 	LCHECKNT(ll>=0,funcname,ECnonexist,"list name not recognized");
995 	return ll;
996  failure:
997 	return (int)Liberrorcode; }
998 
999 
1000 /* smolGetMolListName */
smolGetMolListName(simptr sim,int mollistindex,char * mollist)1001 extern CSTRING char *smolGetMolListName(simptr sim,int mollistindex,char *mollist) {
1002 	const char *funcname="smolGetMolListName";
1003 
1004 	LCHECK(sim,funcname,ECmissing,"missing sim");
1005 	LCHECK(mollistindex>=0,funcname,ECbounds,"mollistindex < 0");
1006 	LCHECK(sim->mols,funcname,ECnonexist,"no molecule lists defined");
1007 	LCHECK(mollistindex<sim->mols->nlist,funcname,ECnonexist,"molecule list doesn't exist");
1008 	LCHECK(mollist,funcname,ECmissing,"missing mollist");
1009 	strcpy(mollist,sim->mols->listname[mollistindex]);
1010 	return mollist;
1011  failure:
1012 	return NULL; }
1013 
1014 
1015 /* smolSetMolList */
smolSetMolList(simptr sim,const char * species,enum MolecState state,const char * mollist)1016 extern CSTRING enum ErrorCode smolSetMolList(simptr sim,const char *species,enum MolecState state,const char *mollist) {
1017 	const char *funcname="smolSetMolList";
1018 	int i,ll;
1019 
1020 	LCHECK(sim,funcname,ECmissing,"missing sim");
1021 	i=smolGetSpeciesIndexNT(sim,species);
1022 	if(i==(int)ECall) {smolClearError();i=-5;}
1023 	else LCHECK(i>0,funcname,ECsame,NULL);
1024 	LCHECK((state>=0 && state<MSMAX) || state==MSall,funcname,ECsyntax,"invalid state");
1025 	ll=smolGetMolListIndexNT(sim,mollist);
1026 	LCHECK(ll>=0,funcname,ECsame,NULL);
1027 	LCHECK(sim->mols->listtype[ll]==MLTsystem,funcname,ECerror,"list is not a system list");
1028 	molsetlistlookup(sim,i,NULL,state,ll);
1029 	return ECok;
1030  failure:
1031 	return Liberrorcode; }
1032 
1033 
1034 /* smolSetMaxMolecules */
smolSetMaxMolecules(simptr sim,int maxmolecules)1035 extern CSTRING enum ErrorCode smolSetMaxMolecules(simptr sim,int maxmolecules) {
1036 	const char *funcname="smolSetMaxMolecules";
1037 	int er;
1038 
1039 	LCHECK(sim,funcname,ECmissing,"missing sim");
1040 	LCHECK(maxmolecules>0,funcname,ECbounds,"maxmolecules needs to be > 0");
1041 	er=molsetmaxmol(sim,maxmolecules);
1042 	LCHECK(!er,funcname,ECmemory,"out of memory allocating molecules");
1043 	return ECok;
1044  failure:
1045 	return Liberrorcode; }
1046 
1047 
1048 /* smolAddSolutionMolecules */
smolAddSolutionMolecules(simptr sim,const char * species,int number,double * lowposition,double * highposition)1049 extern CSTRING enum ErrorCode smolAddSolutionMolecules(simptr sim,const char *species,int number,double *lowposition,double *highposition) {
1050 	const char *funcname="smolAddSolutionMolecules";
1051 	int er,i,d;
1052 	double *low,*high,lowpos[3],highpos[3];
1053 
1054 	LCHECK(sim,funcname,ECmissing,"missing sim");
1055 	i=smolGetSpeciesIndexNT(sim,species);
1056 	LCHECK(i>0,funcname,ECsame,NULL);
1057 	LCHECK(number>=0,funcname,ECbounds,"number cannot be < 0");
1058 	if(!lowposition) {
1059 		for(d=0;d<sim->dim;d++) lowpos[d]=sim->wlist[d*2]->pos;
1060 		low=lowpos; }
1061 	else
1062 		low=lowposition;
1063 	if(!highposition) {
1064 		for(d=0;d<sim->dim;d++) highpos[d]=sim->wlist[d*2+1]->pos;
1065 		high=highpos; }
1066 	else
1067 		high=highposition;
1068 
1069 	er=addmol(sim,number,i,low,high,0);
1070 	LCHECK(!er,funcname,ECmemory,"out of memory adding molecules");
1071 	return ECok;
1072  failure:
1073 	return Liberrorcode; }
1074 
1075 
1076 /* smolAddCompartmentMolecules */
smolAddCompartmentMolecules(simptr sim,const char * species,int number,const char * compartment)1077 extern CSTRING enum ErrorCode smolAddCompartmentMolecules(simptr sim,const char *species,int number,const char *compartment) {
1078 	const char *funcname="smolAddCompartmentMolecules";
1079 	int i,er,c;
1080 
1081 	LCHECK(sim,funcname,ECmissing,"missing sim");
1082 	i=smolGetSpeciesIndexNT(sim,species);
1083 	LCHECK(i>0,funcname,ECsame,NULL);
1084 	LCHECK(number>=0,funcname,ECbounds,"number < 0");
1085 	c=smolGetCompartmentIndexNT(sim,compartment);
1086 	LCHECK(c>=0,funcname,ECsame,NULL);
1087 	er=addcompartmol(sim,number,i,sim->cmptss->cmptlist[c]);
1088 	LCHECK(er!=2,funcname,ECerror,"compartment volume is zero or nearly zero");
1089 	LCHECK(er!=3,funcname,ECmemory,"out of memory adding molecules");
1090 	return ECok;
1091  failure:
1092 	return Liberrorcode; }
1093 
1094 
1095 /* smolAddSurfaceMolecules */
smolAddSurfaceMolecules(simptr sim,const char * species,enum MolecState state,int number,const char * surface,enum PanelShape panelshape,const char * panel,double * position)1096 extern CSTRING enum ErrorCode smolAddSurfaceMolecules(simptr sim,const char *species,enum MolecState state,int number,const char *surface,enum PanelShape panelshape,const char *panel,double *position) {
1097 	const char *funcname="smolAddSurfaceMolecules";
1098 	int i,s,p,er;
1099 	panelptr pnl;
1100 
1101 	LCHECK(sim,funcname,ECmissing,"missing sim");
1102 	i=smolGetSpeciesIndexNT(sim,species);
1103 	LCHECK(i>0,funcname,ECsame,NULL);
1104 	LCHECK(state>=0 && state<MSMAX,funcname,ECsyntax,"invalid state");
1105 	LCHECK(number>=0,funcname,ECbounds,"number < 0");
1106 	s=smolGetSurfaceIndexNT(sim,surface);
1107 	if(s==(int)ECall) {smolClearError();s=-5;}
1108 	else LCHECK(s>=0,funcname,ECsame,NULL);
1109 	LCHECK((panelshape>=0 && panelshape<PSMAX) || panelshape==PSall,funcname,ECnonexist,"invalid panelshape");
1110 	pnl=NULL;
1111 	p=smolGetPanelIndexNT(sim,surface,NULL,panel);
1112 	if(p==(int)ECall) {smolClearError();p=-5;}
1113 	else LCHECK(p>=0,funcname,ECsame,NULL);
1114 
1115 	if(p>=0) {
1116 		LCHECK(s>=0,funcname,ECsyntax,"needs to be specific surface");
1117 		LCHECK(panelshape!=PSall,funcname,ECsyntax,"needs to be specific panelshape");
1118 		pnl=sim->srfss->srflist[s]->panels[panelshape][p]; }
1119 	else {
1120 		LCHECK(!position,funcname,ECsyntax,"a panel must be specified if position is entered"); }
1121 	er=addsurfmol(sim,number,i,state,position,pnl,s,panelshape,NULL);
1122 	LCHECK(er!=1,funcname,ECmemory,"unable to allocate temporary storage space");
1123 	LCHECK(er!=2,funcname,ECbug,"panel name not recognized");
1124 	LCHECK(er!=3,funcname,ECmemory,"out of memory adding molecules");
1125 
1126 	return ECok;
1127  failure:
1128 	return Liberrorcode; }
1129 
1130 
1131 /* smolGetMoleculeCount */
smolGetMoleculeCount(simptr sim,const char * species,enum MolecState state)1132 extern CSTRING int smolGetMoleculeCount(simptr sim,const char *species,enum MolecState state) {
1133 	const char *funcname="smolGetMoleculeCount";
1134 	int i;
1135 
1136 	LCHECK(sim,funcname,ECmissing,"missing sim");
1137 	i=smolGetSpeciesIndexNT(sim,species);
1138 	if(i==(int)ECall) {i=-5;smolClearError();}
1139 	else LCHECK(i>0,funcname,ECsame,NULL);
1140 	return molcount(sim,i,NULL,state,-1);
1141  failure:
1142 	return (int)Liberrorcode; }
1143 
1144 
1145 /* smolSetMoleculeColor */
smolSetMoleculeColor(simptr sim,const char * species,enum MolecState state,double * color)1146 extern "C" enum ErrorCode smolSetMoleculeColor(
1147     simptr sim, const char *species, enum MolecState state, double *color)
1148 {
1149     const char *funcname = "smolSetMoleculeColor";
1150     int i, c;
1151 
1152     LCHECK(sim, funcname, ECmissing, "missing sim");
1153     i = smolGetSpeciesIndexNT(sim, species);
1154     if(i == (int)ECall) {
1155         smolClearError();
1156         i = -5;
1157     }
1158     else
1159         LCHECK(i > 0, funcname, ECsame, NULL);
1160 
1161     LCHECK((state >= 0 && state < MSMAX) || state == MSall, funcname, ECsyntax,
1162         "invalid state");
1163 
1164     for(c = 0; c < 3; c++)
1165         LCHECK(color[c] >= 0 && color[c] <= 1, funcname, ECbounds,
1166             "color value out of bounds");
1167     molsetcolor(sim, i, NULL, state, color);
1168     return ECok;
1169 failure:
1170     return Liberrorcode;
1171 }
1172 
smolSetMoleculeSize(simptr sim,const char * species,enum MolecState state,double size)1173 extern "C" enum ErrorCode smolSetMoleculeSize(
1174     simptr sim, const char *species, enum MolecState state, double size)
1175 {
1176     const char *funcname = "smolSetMoleculeSize";
1177     int i;
1178     LCHECK(sim, funcname, ECmissing, "missing sim");
1179     i = smolGetSpeciesIndexNT(sim, species);
1180     if(i == (int)ECall) {
1181         smolClearError();
1182         i = -5;
1183     }
1184     else
1185         LCHECK(i > 0, funcname, ECsame, NULL);
1186     LCHECK((state >= 0 && state < MSMAX) || state == MSall, funcname, ECsyntax,
1187         "invalid state");
1188 
1189     molsetdisplaysize(sim, i, NULL, state, size);
1190     return ECok;
1191 failure:
1192     return Liberrorcode;
1193 }
1194 
1195 /* smolSetMoleculeStyle */
smolSetMoleculeStyle(simptr sim,const char * species,enum MolecState state,double size,double * color)1196 extern CSTRING enum ErrorCode smolSetMoleculeStyle(simptr sim,const char *species,enum MolecState state,double size,double *color) {
1197 	const char *funcname="smolSetTextStyle";
1198 	int i,c;
1199 
1200 	LCHECK(sim,funcname,ECmissing,"missing sim");
1201 	i=smolGetSpeciesIndexNT(sim,species);
1202 	if(i==(int)ECall) {smolClearError();i=-5;}
1203 	else LCHECK(i>0,funcname,ECsame,NULL);
1204 	LCHECK((state>=0 && state<MSMAX) || state==MSall,funcname,ECsyntax,"invalid state");
1205 
1206 	if(size>0) molsetdisplaysize(sim,i,NULL,state,size);
1207 
1208 	if(color) {
1209 		for(c=0;c<3;c++)
1210 			LCHECK(color[c]>=0 && color[c]<=1,funcname,ECbounds,"color value out of bounds");
1211 		molsetcolor(sim,i,NULL,state,color); }
1212 	return ECok;
1213 failure:
1214 	return Liberrorcode; }
1215 
1216 
1217 /******************************************************************************/
1218 /*********************************** Surfaces *********************************/
1219 /******************************************************************************/
1220 
1221 /* smolSetBoundaryType */
smolSetBoundaryType(simptr sim,int dimension,int highside,char type)1222 extern CSTRING enum ErrorCode smolSetBoundaryType(simptr sim,int dimension,int highside,char type) {
1223 	const char *funcname="smolSetBoundaryType";
1224 	int er;
1225 
1226 	LCHECK(sim,funcname,ECmissing,"missing sim");
1227 	LCHECK(dimension<sim->dim,funcname,ECbounds,"dimension cannot exceed system dimensionality");
1228 	LCHECK(highside<=1,funcname,ECbounds,"highside must be -1, 0, or 1");
1229 	LCHECK(type=='r' || type=='p' || type=='a' || type=='t',funcname,ECsyntax,"invalid type");
1230 	er=wallsettype(sim,dimension,highside,type);
1231 	LCHECK(!er,funcname,ECbug,"bug in wallsettype");
1232 	return ECok;
1233  failure:
1234 	return Liberrorcode; }
1235 
1236 
1237 /* smolAddSurface */
smolAddSurface(simptr sim,const char * surface)1238 extern CSTRING enum ErrorCode smolAddSurface(simptr sim,const char *surface) {
1239 	const char *funcname="smolAddSurface";
1240 	int s;
1241 	surfaceptr srf;
1242 
1243 	LCHECK(sim,funcname,ECmissing,"missing sim");
1244 	s=smolGetSurfaceIndexNT(sim,surface);
1245 	if(s==(int)ECnonexist) smolClearError();
1246 	else if(s<0) LCHECK(0,funcname,ECsame,NULL);
1247 	else LCHECK(0,funcname,ECerror,"surface is already in system");
1248 	srf=surfaddsurface(sim,surface);
1249 	LCHECK(srf,funcname,ECmemory,"out of memory adding surface");
1250 	return ECok;
1251  failure:
1252 	return Liberrorcode; }
1253 
1254 
1255 /* smolGetSurfaceIndex */
smolGetSurfaceIndex(simptr sim,const char * surface)1256 extern CSTRING int smolGetSurfaceIndex(simptr sim,const char *surface) {
1257 	const char *funcname="smolGetSurfaceIndex";
1258 	int s;
1259 
1260 	LCHECK(sim,funcname,ECmissing,"missing sim");
1261 	LCHECK(surface,funcname,ECmissing,"missing surface");
1262 	LCHECK(sim->srfss && sim->srfss->nsrf,funcname,ECnonexist,"no surfaces defined");
1263 	LCHECK(strcmp(surface,"all"),funcname,ECall,"surface cannot be 'all'");
1264 	s=stringfind(sim->srfss->snames,sim->srfss->nsrf,surface);
1265 	LCHECK(s>=0,funcname,ECnonexist,"surface not found");
1266 	return s;
1267  failure:
1268 	return (int)Liberrorcode; }
1269 
1270 
1271 /* smolGetSurfaceIndexNT */
smolGetSurfaceIndexNT(simptr sim,const char * surface)1272 extern CSTRING int smolGetSurfaceIndexNT(simptr sim,const char *surface) {
1273 	const char *funcname="smolGetSurfaceIndexNT";
1274 	int s;
1275 
1276 	LCHECKNT(sim,funcname,ECmissing,"missing sim");
1277 	LCHECKNT(surface,funcname,ECmissing,"missing surface");
1278 	LCHECKNT(sim->srfss && sim->srfss->nsrf,funcname,ECnonexist,"no surfaces defined");
1279 	LCHECKNT(strcmp(surface,"all"),funcname,ECall,"surface cannot be 'all'");
1280 	s=stringfind(sim->srfss->snames,sim->srfss->nsrf,surface);
1281 	LCHECKNT(s>=0,funcname,ECnonexist,"surface not found");
1282 	return s;
1283  failure:
1284 	return (int)Liberrorcode; }
1285 
1286 
1287 /* smolGetSurfaceName */
smolGetSurfaceName(simptr sim,int surfaceindex,char * surface)1288 extern CSTRING char *smolGetSurfaceName(simptr sim,int surfaceindex,char *surface) {
1289 	const char *funcname="smolGetSurfaceName";
1290 
1291 	LCHECK(sim,funcname,ECmissing,"missing sim");
1292 	LCHECK(surfaceindex>=0,funcname,ECbounds,"invalid surface index");
1293 	LCHECK(surface,funcname,ECmissing,"missing surface");
1294 	LCHECK(sim->srfss && sim->srfss->nsrf,funcname,ECnonexist,"no surfaces defined");
1295 	LCHECK(surfaceindex<sim->srfss->nsrf,funcname,ECnonexist,"surface does not exist");
1296 	strcpy(surface,sim->srfss->snames[surfaceindex]);
1297 	return surface;
1298  failure:
1299 	return NULL; }
1300 
1301 
1302 /* smolSetSurfaceAction */
smolSetSurfaceAction(simptr sim,const char * surface,enum PanelFace face,const char * species,enum MolecState state,enum SrfAction action,const char * newspecies)1303 extern CSTRING enum ErrorCode smolSetSurfaceAction(simptr sim,const char *surface,enum PanelFace face,const char *species,enum MolecState state,enum SrfAction action,const char *newspecies) {
1304 	const char *funcname="smolSetSurfaceAction";
1305 	int er,i,s,i2;
1306 	surfaceptr srf;
1307 
1308 	LCHECK(sim,funcname,ECmissing,"missing sim");
1309 	s=smolGetSurfaceIndexNT(sim,surface);
1310 	if(s==(int)ECall) {smolClearError();s=-5;}
1311 	else LCHECK(s>=0,funcname,ECsame,NULL);
1312 	LCHECK(face==PFfront || face==PFback || face==PFboth,funcname,ECbounds,"invalid face");
1313 	i=smolGetSpeciesIndexNT(sim,species);
1314 	if(i==(int)ECall) {smolClearError();i=-5;}
1315 	else LCHECK(i>0,funcname,ECsame,NULL);
1316 	LCHECK((state>=0 && state<MSMAX) || state==MSall,funcname,ECbounds,"invalid state");
1317 	LCHECK(action>=0 && action<=SAmult,funcname,ECbounds,"invalid action");
1318         if(newspecies && strlen(newspecies) > 0) {
1319             i2=smolGetSpeciesIndexNT(sim,newspecies);
1320             LCHECK(i2>0,funcname,ECnonexist,"unrecognized new species name"); }
1321         else
1322             i2=0;
1323         if(s>=0) {
1324             srf=sim->srfss->srflist[s];
1325             er=surfsetaction(srf,i,NULL,state,face,action,0);
1326             LCHECK(!er,funcname,ECbug,"bug in surfsetaction"); }
1327         else {
1328             for(s=0;s<sim->srfss->nsrf;s++) {
1329                 srf=sim->srfss->srflist[s];
1330                 er=surfsetaction(srf,i,NULL,state,face,action,0);
1331                 LCHECK(!er,funcname,ECbug,"bug in surfsetaction"); }}
1332         return ECok;
1333  failure:
1334 	return Liberrorcode; }
1335 
1336 
1337 /* smolSetSurfaceRate */
smolSetSurfaceRate(simptr sim,const char * surface,const char * species,enum MolecState state,enum MolecState state1,enum MolecState state2,double rate,const char * newspecies,int isinternal)1338 extern CSTRING enum ErrorCode smolSetSurfaceRate(simptr sim,const char *surface,const char *species,enum MolecState state,enum MolecState state1,enum MolecState state2,double rate,const char *newspecies,int isinternal) {
1339 	const char *funcname="smolSetSurfaceRate";
1340 	int er,i,i2,s;
1341 	surfaceptr srf;
1342 
1343 	LCHECK(sim,funcname,ECmissing,"missing sim");
1344 	s=smolGetSurfaceIndexNT(sim,surface);
1345 	if(s==(int)ECall) {smolClearError();s=-5;}
1346 	else LCHECK(s>=0,funcname,ECsame,NULL);
1347 	i=smolGetSpeciesIndexNT(sim,species);
1348 	if(i==(int)ECall) {smolClearError();i=-5;}
1349 	else LCHECK(i>0,funcname,ECsame,NULL);
1350 	LCHECK(state>=0 && state<MSMAX,funcname,ECbounds,"invalid state");
1351 	LCHECK(state1>=0 && state1<MSMAX1,funcname,ECbounds,"invalid state1");
1352 	LCHECK(state==MSsoln || state1==MSsoln || state1==MSbsoln || state1==state,funcname,ECsyntax,"nonsensical state combination");
1353 	LCHECK(state2>=0 && state2<MSMAX1,funcname,ECbounds,"invalid state2");
1354 	LCHECK(state1!=state2,funcname,ECsyntax,"cannot set rate for state1 = state2");
1355 	if(newspecies && newspecies[0]!='\0') {
1356 		i2=smolGetSpeciesIndexNT(sim,newspecies);
1357 		LCHECK(i2>0,funcname,ECerror,"invalid newspecies"); }
1358 	else i2=-5;
1359 	LCHECK(rate>=0,funcname,ECbounds,"rate needs to be non-negative");
1360 	LCHECK(!(isinternal && rate>1),funcname,ECbounds,"internal rate needs to be <= 1");
1361 
1362 	if(s>=0) {
1363 		srf=sim->srfss->srflist[s];
1364 		er=surfsetrate(srf,i,NULL,state,state1,state2,i2,rate,isinternal?2:1);
1365 		LCHECK(!er,funcname,ECerror,"error in surfsetrate"); }
1366 	else {
1367 		for(s=0;s<sim->srfss->nsrf;s++) {
1368 			srf=sim->srfss->srflist[s];
1369 			er=surfsetrate(srf,i,NULL,state,state1,state2,i2,rate,isinternal?2:1);
1370 			LCHECK(!er,funcname,ECerror,"error in surfsetrate"); }}
1371 	return ECok;
1372  failure:
1373 	return Liberrorcode; }
1374 
1375 
1376 /* smolAddPanel */
smolAddPanel(simptr sim,const char * surface,enum PanelShape panelshape,const char * panel,const char * axisstring,double * params)1377 extern CSTRING enum ErrorCode smolAddPanel(simptr sim,const char *surface,enum PanelShape panelshape,const char *panel,const char *axisstring,double *params) {
1378 	const char *funcname="smolAddPanel";
1379 	int er,s;
1380 	surfaceptr srf;
1381 
1382 	LCHECK(sim,funcname,ECmissing,"missing sim");
1383 	s=smolGetSurfaceIndexNT(sim,surface);
1384 	LCHECK(s>=0,funcname,ECsame,NULL);
1385 	LCHECK(panelshape>=0 && panelshape<PSMAX,funcname,ECnonexist,"invalid panel shape");
1386 	if(panelshape==PSrect) {
1387 		LCHECK(axisstring,funcname,ECmissing,"missing axisstring"); }
1388 	LCHECK(params,funcname,ECmissing,"missing params");
1389 	srf=sim->srfss->srflist[s];
1390 	er=surfaddpanel(srf,sim->dim,panelshape,axisstring,params,panel);
1391 	LCHECK(er!=-1,funcname,ECmemory,"out of memory adding panel");
1392 	LCHECK(er!=3,funcname,ECsyntax,"cannot parse axisstring");
1393 	LCHECK(er!=4,funcname,ECbounds,"drawing slices and stacks need to be positive");
1394 	LCHECK(er!=5,funcname,ECbounds,"cylinder ends cannot be at the same location");
1395 	LCHECK(er!=6,funcname,ECbounds,"hemisphere outward pointing vector has zero length");
1396 	LCHECK(er!=7,funcname,ECbounds,"radius needs to be positive");
1397 	LCHECK(er!=8,funcname,ECbounds,"normal vector has zero length");
1398 	LCHECK(er!=9,funcname,ECerror,"panel name was used before for a different panel shape");
1399 	LCHECK(!er,funcname,ECbug,"bug in smolAddPanel");
1400 	return ECok;
1401  failure:
1402 	return Liberrorcode; }
1403 
1404 
1405 /* smolGetPanelIndex */
smolGetPanelIndex(simptr sim,const char * surface,enum PanelShape * panelshapeptr,const char * panel)1406 extern CSTRING int smolGetPanelIndex(simptr sim,const char *surface,enum PanelShape *panelshapeptr,const char *panel) {
1407 	const char *funcname="smolGetPanelIndex";
1408 	surfaceptr srf;
1409 	int p,s;
1410 	enum PanelShape ps;
1411 
1412 	LCHECK(sim,funcname,ECmissing,"missing sim");
1413 	s=smolGetSurfaceIndexNT(sim,surface);
1414 	LCHECK(s>=0,funcname,ECsame,NULL);
1415 	LCHECK(panel,funcname,ECmissing,"missing panel name");
1416 	LCHECK(strcmp(panel,"all"),funcname,ECall,"panel cannot be 'all'");
1417 	srf=sim->srfss->srflist[s];
1418 	p=-1;
1419 
1420 #if 0
1421 	for(ps=(enum PanelShape)0;ps<(enum PanelShape)PSMAX && p<0;ps=(enum PanelShape)(ps+1))
1422 		p=stringfind(srf->pname[ps],srf->npanel[ps],panel);
1423 #else
1424         for(auto ips : AllPanels_arr) {
1425             int _ips = static_cast<int>(ips);
1426             p        = stringfind(srf->pname[_ips], srf->npanel[_ips], panel);
1427             if(p >= 0) {
1428                 ps = ips;
1429                 break;
1430             }
1431         }
1432 #endif
1433 
1434 	LCHECK(p>=0,funcname,ECnonexist,"panel not found");
1435 	if(panelshapeptr) *panelshapeptr=ps;
1436 	return p;
1437  failure:
1438 	return (int)Liberrorcode; }
1439 
1440 
1441 /* smolGetPanelIndexNT */
smolGetPanelIndexNT(simptr sim,const char * surface,enum PanelShape * panelshapeptr,const char * panel)1442 extern CSTRING int smolGetPanelIndexNT(simptr sim,const char *surface,enum PanelShape *panelshapeptr,const char *panel) {
1443 	const char *funcname="smolGetPanelIndexNT";
1444 	surfaceptr srf;
1445 	int p,s;
1446 	enum PanelShape ps;
1447 
1448 	LCHECKNT(sim,funcname,ECmissing,"missing sim");
1449 	s=smolGetSurfaceIndexNT(sim,surface);
1450 	LCHECKNT(s>=0,funcname,ECsame,NULL);
1451 	LCHECKNT(panel,funcname,ECmissing,"missing panel name");
1452 	LCHECKNT(strcmp(panel,"all"),funcname,ECall,"panel cannot be 'all'");
1453 	srf=sim->srfss->srflist[s];
1454 	p=-1;
1455 #if 0
1456 	for(ps=(enum PanelShape)0;ps<(enum PanelShape)PSMAX && p<0;ps=(enum PanelShape)(ps+1))
1457 		p=stringfind(srf->pname[ps],srf->npanel[ps],panel);
1458 #else
1459     for(auto ips : AllPanels_arr) {
1460         int _ips = static_cast<int>(ips);
1461         p        = stringfind(srf->pname[_ips], srf->npanel[_ips], panel);
1462         if(p >= 0) {
1463             ps = ips;
1464             break;
1465         }
1466     }
1467 #endif
1468 	LCHECKNT(p>=0,funcname,ECnonexist,"panel not found");
1469 	if(panelshapeptr) *panelshapeptr=ps;
1470 	return p;
1471  failure:
1472 	return (int)Liberrorcode; }
1473 
1474 
1475 /* smolGetPanelName */
smolGetPanelName(simptr sim,const char * surface,enum PanelShape panelshape,int panelindex,char * panel)1476 extern CSTRING char *smolGetPanelName(simptr sim,const char *surface,enum PanelShape panelshape,int panelindex,char *panel) {
1477 	const char *funcname="smolGetPanelName";
1478 	surfaceptr srf;
1479 	int s;
1480 
1481 	LCHECK(sim,funcname,ECmissing,"missing sim");
1482 	s=smolGetSurfaceIndexNT(sim,surface);
1483 	LCHECK(s>=0,funcname,ECsame,NULL);
1484 	LCHECK(panelshape>=0 && panelshape<PSMAX,funcname,ECnonexist,"invalid panel shape");
1485 	LCHECK(panelindex>=0,funcname,ECbounds,"invalid panel index");
1486 	LCHECK(panel,funcname,ECmissing,"missing panel name");
1487 	srf=sim->srfss->srflist[s];
1488 	LCHECK(panelindex<srf->npanel[panelshape],funcname,ECnonexist,"no panel exists with this number");
1489 	strcpy(panel,srf->pname[panelshape][panelindex]);
1490 	return panel;
1491  failure:
1492 	return NULL; }
1493 
1494 
1495 /* smolSetPanelJump */
smolSetPanelJump(simptr sim,const char * surface,const char * panel1,enum PanelFace face1,const char * panel2,enum PanelFace face2,int isbidirectional)1496 extern CSTRING enum ErrorCode smolSetPanelJump(simptr sim,const char *surface,const char *panel1,enum PanelFace face1,const char *panel2,enum PanelFace face2,int isbidirectional) {
1497 	const char *funcname="smolSetPanelJump";
1498 	int s,p1,p2,er;
1499 	surfaceptr srf;
1500 	enum PanelShape ps1,ps2;
1501 	panelptr pnl1,pnl2;
1502 
1503 	LCHECK(sim,funcname,ECmissing,"missing sim");
1504 	s=smolGetSurfaceIndexNT(sim,surface);
1505 	LCHECK(s>=0,funcname,ECsame,NULL);
1506 	p1=smolGetPanelIndexNT(sim,surface,&ps1,panel1);
1507 	LCHECK(p1>=0,funcname,ECsame,NULL);
1508 	p2=smolGetPanelIndexNT(sim,surface,&ps2,panel2);
1509 	LCHECK(p2>=0,funcname,ECsame,NULL);
1510 	LCHECK(ps1==ps2,funcname,ECerror,"origin and destination jump panels need to have the same shape");
1511 	LCHECK(p1!=p2,funcname,ECerror,"origin and destination jump panels cannot be the same panel");
1512 	LCHECK(face1==PFfront || face1==PFback,funcname,ECsyntax,"jumping panel face has to be either front or back");
1513 	LCHECK(face2==PFfront || face2==PFback,funcname,ECsyntax,"jumping panel face has to be either front or back");
1514 	LCHECK(isbidirectional==0 || isbidirectional==1,funcname,ECsyntax,"bidirectional code has to be 0 or 1");
1515 
1516 	srf=sim->srfss->srflist[s];
1517 	pnl1=srf->panels[ps1][p1];
1518 	pnl2=srf->panels[ps2][p2];
1519 	er=surfsetjumppanel(srf,pnl1,face1,isbidirectional,pnl2,face2);
1520 	LCHECK(!er,funcname,ECbug,"BUG: error code returned by surfsetjumppanel");
1521 	return ECok;
1522  failure:
1523 	return Liberrorcode; }
1524 
1525 
1526 /* smolAddSurfaceUnboundedEmitter */
smolAddSurfaceUnboundedEmitter(simptr sim,const char * surface,enum PanelFace face,const char * species,double emitamount,double * emitposition)1527 extern CSTRING enum ErrorCode smolAddSurfaceUnboundedEmitter(simptr sim,const char *surface,enum PanelFace face,const char *species,double emitamount,double *emitposition) {
1528 	const char *funcname="smolAddSurfaceUnboundedEmitter";
1529 	int s,i,er;
1530 	surfaceptr srf;
1531 
1532 	LCHECK(sim,funcname,ECmissing,"missing sim");
1533 	s=smolGetSurfaceIndexNT(sim,surface);
1534 	LCHECK(s>=0,funcname,ECsame,NULL);
1535 	LCHECK(face==PFfront || face==PFback,funcname,ECsyntax,"jumping panel face has to be either front or back");
1536 	i=smolGetSpeciesIndexNT(sim,species);
1537 	LCHECK(i>0,funcname,ECsame,NULL);
1538 
1539 	srf=sim->srfss->srflist[s];
1540 	er=surfaddemitter(srf,face,i,emitamount,emitposition,sim->dim);
1541 	LCHECK(!er,funcname,ECmemory,"out of memory allocating unbounded emitter");
1542 
1543 	return ECok;
1544  failure:
1545 	return Liberrorcode; }
1546 
1547 
1548 /* smolSetSurfaceSimParams */
smolSetSurfaceSimParams(simptr sim,const char * parameter,double value)1549 extern CSTRING enum ErrorCode smolSetSurfaceSimParams(simptr sim,const char *parameter,double value) {
1550 	const char *funcname="smolSetSurfaceSimParams";
1551 	int er;
1552 
1553 	LCHECK(sim,funcname,ECmissing,"missing sim");
1554 	LCHECK(parameter,funcname,ECmissing,"missing parameter name");
1555 	if(!strcmp(parameter,"epsilon")) {
1556 		er=surfsetepsilon(sim,value);
1557 		LCHECK(er!=2,funcname,ECmemory,"out of memory enabling surfaces");
1558 		LCHECK(er!=3,funcname,ECbounds,"epsilon needs to be >0"); }
1559 	else if(!strcmp(parameter,"margin")) {
1560 		er=surfsetmargin(sim,value);
1561 		LCHECK(er!=2,funcname,ECmemory,"out of memory enabling surfaces");
1562 		LCHECK(er!=3,funcname,ECbounds,"margin needs to be >=0"); }
1563 	else if(!strcmp(parameter,"neighbordist")) {
1564 		er=surfsetneighdist(sim,value);
1565 		LCHECK(er!=2,funcname,ECmemory,"out of memory enabling surfaces");
1566 		LCHECK(er!=3,funcname,ECbounds,"neighbor distance needs to be >0"); }
1567 	else
1568 		LCHECK(0,funcname,ECsyntax,"parameter name not recognized");
1569 
1570 	return ECok;
1571  failure:
1572 	return Liberrorcode; }
1573 
1574 
1575 /* smolAddPanelNeighbor */
smolAddPanelNeighbor(simptr sim,const char * surface1,const char * panel1,const char * surface2,const char * panel2,int reciprocal)1576 extern CSTRING enum ErrorCode smolAddPanelNeighbor(simptr sim,const char *surface1,const char *panel1,const char *surface2,const char *panel2,int reciprocal) {
1577 	const char *funcname="smolAddPanelNeighbor";
1578 	int s1,s2,p1,p2,er;
1579 	panelptr pnl1,pnl2;
1580 	enum PanelShape ps1,ps2;
1581 
1582 	LCHECK(sim,funcname,ECmissing,"missing sim");
1583 	s1=smolGetSurfaceIndexNT(sim,surface1);
1584 	LCHECK(s1>=0,funcname,ECsame,NULL);
1585 	s2=smolGetSurfaceIndexNT(sim,surface2);
1586 	LCHECK(s2>=0,funcname,ECsame,NULL);
1587 	p1=smolGetPanelIndexNT(sim,surface1,&ps1,panel1);
1588 	LCHECK(p1>=0,funcname,ECsame,NULL);
1589 	p2=smolGetPanelIndexNT(sim,surface2,&ps2,panel2);
1590 	LCHECK(p2>=0,funcname,ECsame,NULL);
1591 	LCHECK(!(s1==s2 && p1==p2 && ps1 == ps2),funcname,ECerror,"panels cannot be their own neighbors");
1592 
1593 	pnl1=sim->srfss->srflist[s1]->panels[ps1][p1];
1594 	pnl2=sim->srfss->srflist[s2]->panels[ps2][p2];
1595 	er=surfsetneighbors(pnl1,&pnl2,1,1);
1596 	LCHECK(!er,funcname,ECmemory,"out of memory adding panel neighbor");
1597 	if(reciprocal) {
1598 		er=surfsetneighbors(pnl2,&pnl1,1,1);
1599 		LCHECK(!er,funcname,ECmemory,"out of memory adding panel neighbor"); }
1600 
1601 	return ECok;
1602 failure:
1603 	return Liberrorcode; }
1604 
1605 
1606 /* smolSetSurfaceStyle */
smolSetSurfaceStyle(simptr sim,const char * surface,enum PanelFace face,enum DrawMode mode,double thickness,double * color,int stipplefactor,int stipplepattern,double shininess)1607 extern CSTRING enum ErrorCode smolSetSurfaceStyle(simptr sim,const char *surface,enum PanelFace face,enum DrawMode mode,double thickness,double *color,int stipplefactor,int stipplepattern,double shininess) {
1608 	const char *funcname="smolSetSurfaceFaceStyle";
1609 	int s,c,er;
1610 	surfaceptr srf;
1611 
1612 	LCHECK(sim,funcname,ECmissing,"missing sim");
1613 	s=smolGetSurfaceIndexNT(sim,surface);
1614 	if(s==(int)ECall) {smolClearError();s=-5;}
1615 	else LCHECK(s>=0,funcname,ECsame,NULL);
1616 	srf=sim->srfss->srflist[s];
1617 
1618 	if(mode!=DMnone) {
1619 		LCHECK(mode>=0 && mode<DMnone,funcname,ECsyntax,"mode not recognized");
1620 		er=surfsetdrawmode(srf,face,mode);
1621 		LCHECK(!er,funcname,ECbug,"BUG: error in surfsetdrawmode"); }
1622 	if(thickness>=0) {
1623 		er=surfsetedgepts(srf,thickness);
1624 		LCHECK(!er,funcname,ECbug,"BUG: error in surfsetedgepts"); }
1625 	if(color) {
1626 		for(c=0;c<4;c++)
1627 			LCHECK(color[c]>=0 && color[c]<=1,funcname,ECbounds,"color value out of bounds");
1628 		er=surfsetcolor(srf,face,color);
1629 		LCHECK(!er,funcname,ECbug,"BUG: error in surfsetcolor"); }
1630 	if(stipplefactor>=0) {
1631 		LCHECK(stipplefactor>0,funcname,ECbounds,"stipplefactor needs to be >0");
1632 		er=surfsetstipple(srf,stipplefactor,-1);
1633 		LCHECK(!er,funcname,ECbug,"BUG: error in surfsetstipple"); }
1634 	if(stipplepattern>=0) {
1635 		LCHECK(stipplepattern<=0xFFFF,funcname,ECbounds,"stipplepattern needs to be between 0 and 0xFFFF");
1636 		er=surfsetstipple(srf,-1,stipplepattern);
1637 		LCHECK(!er,funcname,ECbug,"BUG: error in surfsetstipple"); }
1638 	if(shininess>=0) {
1639 		LCHECK(shininess<=128,funcname,ECbounds,"shininess cannot exceed 128");
1640 		er=surfsetshiny(srf,face,shininess);
1641 		LCHECK(!er,funcname,ECbug,"BUG: error in surfsetshiny"); }
1642 
1643 	return ECok;
1644 failure:
1645 	return Liberrorcode; }
1646 
1647 
1648 /******************************************************************************/
1649 /******************************** Compartments ********************************/
1650 /******************************************************************************/
1651 
1652 /* smolAddCompartment */
smolAddCompartment(simptr sim,const char * compartment)1653 extern CSTRING enum ErrorCode smolAddCompartment(simptr sim,const char *compartment) {
1654 	const char *funcname="smolAddCompartment";
1655 	int c;
1656 	compartptr cmpt;
1657 
1658 	LCHECK(sim,funcname,ECmissing,"missing sim");
1659 	c=smolGetCompartmentIndexNT(sim,compartment);
1660 	if(c==(int)ECnonexist) smolClearError();
1661 	else if(c<0) LCHECK(0,funcname,ECsame,NULL);
1662 	else LCHECK(0,funcname,ECerror,"compartment is already in system");
1663 	cmpt=compartaddcompart(sim,compartment);
1664 	LCHECK(cmpt,funcname,ECmemory,"out of memory adding compartment");
1665 	return ECok;
1666  failure:
1667 	return Liberrorcode; }
1668 
1669 
1670 /* smolGetCompartmentIndex */
smolGetCompartmentIndex(simptr sim,const char * compartment)1671 extern CSTRING int smolGetCompartmentIndex(simptr sim,const char *compartment) {
1672 	const char *funcname="smolGetCompartmentIndex";
1673 	int c;
1674 
1675 	LCHECK(sim,funcname,ECmissing,"missing sim");
1676 	LCHECK(compartment,funcname,ECmissing,"missing compartment");
1677 	LCHECK(sim->cmptss && sim->cmptss->ncmpt,funcname,ECnonexist,"no compartments defined");
1678 	LCHECK(strcmp(compartment,"all"),funcname,ECall,"compartment cannot be 'all'");
1679 	c=stringfind(sim->cmptss->cnames,sim->cmptss->ncmpt,compartment);
1680 	LCHECK(c>=0,funcname,ECnonexist,"compartment not found");
1681 	return c;
1682  failure:
1683 	return (int)Liberrorcode; }
1684 
1685 
1686 /* smolGetCompartmentIndexNT */
smolGetCompartmentIndexNT(simptr sim,const char * compartment)1687 extern CSTRING int smolGetCompartmentIndexNT(simptr sim,const char *compartment) {
1688 	const char *funcname="smolGetCompartmentIndexNT";
1689 	int c;
1690 
1691 	LCHECKNT(sim,funcname,ECmissing,"missing sim");
1692 	LCHECKNT(compartment,funcname,ECmissing,"missing compartment");
1693 	LCHECKNT(sim->cmptss && sim->cmptss->ncmpt,funcname,ECnonexist,"no compartments defined");
1694 	LCHECKNT(strcmp(compartment,"all"),funcname,ECall,"compartment cannot be 'all'");
1695 	c=stringfind(sim->cmptss->cnames,sim->cmptss->ncmpt,compartment);
1696 	LCHECKNT(c>=0,funcname,ECnonexist,"compartment not found");
1697 	return c;
1698  failure:
1699 	return (int)Liberrorcode; }
1700 
1701 
1702 /* smolGetCompartmentName */
smolGetCompartmentName(simptr sim,int compartmentindex,char * compartment)1703 extern CSTRING char *smolGetCompartmentName(simptr sim,int compartmentindex,char *compartment) {
1704 	const char *funcname="smolGetCompartmentName";
1705 
1706 	LCHECK(sim,funcname,ECmissing,"missing sim");
1707 	LCHECK(compartmentindex>=0,funcname,ECbounds,"invalid compartment index");
1708 	LCHECK(compartment,funcname,ECmissing,"missing compartment string");
1709 	LCHECK(sim->cmptss && sim->cmptss->ncmpt,funcname,ECnonexist,"no compartments defined");
1710 	LCHECK(compartmentindex<sim->cmptss->ncmpt,funcname,ECnonexist,"compartment does not exist");
1711 	strcpy(compartment,sim->cmptss->cnames[compartmentindex]);
1712 	return compartment;
1713  failure:
1714 	return NULL; }
1715 
1716 
1717 /* smolAddCompartmentSurface */
smolAddCompartmentSurface(simptr sim,const char * compartment,const char * surface)1718 extern CSTRING enum ErrorCode smolAddCompartmentSurface(simptr sim,const char *compartment,const char *surface) {
1719 	const char *funcname="smolAddCompartmentSurface";
1720 	int c,s,er;
1721 
1722 	LCHECK(sim,funcname,ECmissing,"missing sim");
1723 	c=smolGetCompartmentIndexNT(sim,compartment);
1724 	LCHECK(c>=0,funcname,ECsame,NULL);
1725 	s=smolGetSurfaceIndexNT(sim,surface);
1726 	LCHECK(s>=0,funcname,ECsame,NULL);
1727 	er=compartaddsurf(sim->cmptss->cmptlist[c],sim->srfss->srflist[s]);
1728 	LCHECK(!er,funcname,ECmemory,"out of memory in compartaddsurf");
1729 	return ECok;
1730  failure:
1731 	return Liberrorcode; }
1732 
1733 
1734 /* smolAddCompartmentPoint */
smolAddCompartmentPoint(simptr sim,const char * compartment,double * point)1735 extern CSTRING enum ErrorCode smolAddCompartmentPoint(simptr sim,const char *compartment,double *point) {
1736 	const char *funcname="smolAddCompartmentPoint";
1737 	int c,er;
1738 
1739 	LCHECK(sim,funcname,ECmissing,"missing sim");
1740 	c=smolGetCompartmentIndexNT(sim,compartment);
1741 	LCHECK(c>=0,funcname,ECsame,NULL);
1742 	LCHECK(point,funcname,ECmissing,"missing point");
1743 	er=compartaddpoint(sim->cmptss->cmptlist[c],sim->dim,point);
1744 	LCHECK(!er,funcname,ECmemory,"out of memory in compartaddsurf");
1745 	return ECok;
1746  failure:
1747 	return Liberrorcode; }
1748 
1749 
1750 /* smolAddCompartmentLogic */
smolAddCompartmentLogic(simptr sim,const char * compartment,enum CmptLogic logic,const char * compartment2)1751 extern CSTRING enum ErrorCode smolAddCompartmentLogic(simptr sim,const char *compartment,enum CmptLogic logic,const char *compartment2) {
1752 	const char *funcname="smolAddCompartmentLogic";
1753 	int c,c2,er;
1754 
1755 	LCHECK(sim,funcname,ECmissing,"missing sim");
1756 	c=smolGetCompartmentIndexNT(sim,compartment);
1757 	LCHECK(c>=0,funcname,ECsame,NULL);
1758 	LCHECK(logic>=CLequal && logic<CLnone,funcname,ECsyntax,"invalid logic operation");
1759 	c2=smolGetCompartmentIndexNT(sim,compartment2);
1760 	LCHECK(c2>=0,funcname,ECerror,"error with compartment2");
1761 	er=compartaddcmptl(sim->cmptss->cmptlist[c],sim->cmptss->cmptlist[c2],logic);
1762 	LCHECK(!er,funcname,ECmemory,"out of memory in compartaddcmpt");
1763 	return ECok;
1764  failure:
1765 	return Liberrorcode; }
1766 
1767 
1768 
1769 /******************************************************************************/
1770 /********************************* Reactions **********************************/
1771 /******************************************************************************/
1772 
1773 /* smolAddReaction */
smolAddReaction(simptr sim,const char * reaction,const char * reactant1,enum MolecState rstate1,const char * reactant2,enum MolecState rstate2,int nproduct,const char ** productspecies,enum MolecState * productstates,double rate)1774 extern CSTRING enum ErrorCode smolAddReaction(simptr sim,const char *reaction,const char *reactant1,enum MolecState rstate1,const char *reactant2,enum MolecState rstate2,int nproduct,const char **productspecies,enum MolecState *productstates,double rate) {
1775 	const char *funcname="smolAddReaction";
1776 	rxnptr rxn;
1777 	int order,prd,rctident[MAXORDER],prdident[MAXPRODUCT],er;
1778 	enum MolecState rctstate[MAXORDER];
1779 
1780 	LCHECK(sim,funcname,ECmissing,"missing sim");
1781 	LCHECK(reaction,funcname,ECmissing,"missing reaction name");
1782 	order=0;
1783 	rctident[0]=rctident[1]=0;
1784 	rctstate[0]=rctstate[1]=MSnone;
1785 	if(reactant1 && reactant1[0]!='\0') {
1786 		rctident[order]=smolGetSpeciesIndexNT(sim,reactant1);
1787 		LCHECK(rctident[order]>0,funcname,ECsame,NULL);
1788 		LCHECK(rstate1>=0 && rstate1<=MSMAX,funcname,ECbounds,"invalid rstate1");
1789 		rctstate[order]=rstate1;
1790 		order++; }
1791 	if(reactant2 && reactant2[0]!='\0') {
1792 		rctident[order]=smolGetSpeciesIndexNT(sim,reactant2);
1793 		LCHECK(rctident[order]>0,funcname,ECsame,NULL);
1794 		LCHECK(rstate2>=0 && rstate2<=MSMAX,funcname,ECbounds,"invalid rstate2");
1795 		rctstate[order]=rstate2;
1796 		order++; }
1797 	LCHECK(nproduct>=0,funcname,ECbounds,"invalid nproduct");
1798 	if(nproduct) {
1799 		LCHECK(productspecies,funcname,ECmissing,"missing product species");
1800 		LCHECK(productstates,funcname,ECmissing,"missing product states");
1801 		for(prd=0;prd<nproduct;prd++) {
1802 			prdident[prd]=smolGetSpeciesIndexNT(sim,productspecies[prd]);
1803 			LCHECK(prdident[prd]>0,funcname,ECsame,NULL);
1804 			LCHECK(productstates[prd]>=MSsoln && productstates[prd]<=MSMAX,funcname,ECsyntax,"invalid product state"); }}
1805 	rxn=RxnAddReaction(sim,reaction,order,rctident,rctstate,nproduct,prdident,productstates,NULL,NULL);
1806 	LCHECK(rxn,funcname,ECmemory,"out of memory allocating reaction");
1807 
1808 	if(rate>=0) {
1809 		er=RxnSetValue(sim,"rate",rxn,rate);
1810 		if(er==3) LCHECK(0,funcname,ECwarning,"rate was set previously");
1811 		else LCHECK(!er,funcname,ECbug,"RxnSetValue error"); }
1812 
1813 	return Libwarncode;
1814  failure:
1815 	return Liberrorcode; }
1816 
1817 
1818 /* smolGetReactionIndex */
smolGetReactionIndex(simptr sim,int * orderptr,const char * reaction)1819 extern CSTRING int smolGetReactionIndex(simptr sim,int *orderptr,const char *reaction) {
1820 	const char *funcname="smolGetReactionIndex";
1821 	int order,r;
1822 
1823 	LCHECK(sim,funcname,ECmissing,"missing sim");
1824 	LCHECK(reaction,funcname,ECmissing,"missing reaction");
1825 	LCHECK(strcmp(reaction,"all"),funcname,ECall,"reaction cannot be 'all'");
1826 	if(orderptr && *orderptr>=0 && *orderptr<MAXORDER) {
1827 		order=*orderptr;
1828 		LCHECK(sim->rxnss[order] && sim->rxnss[order]->totrxn,funcname,ECnonexist,"no reactions defined of this order");
1829 		r=stringfind(sim->rxnss[order]->rname,sim->rxnss[order]->totrxn,reaction);
1830 		LCHECK(r>=0,funcname,ECnonexist,"reaction not found"); }
1831 	else {
1832 		r=-1;
1833 		for(order=0;order<MAXORDER && r<0;order++)
1834 			if(sim->rxnss[order])
1835 				r=stringfind(sim->rxnss[order]->rname,sim->rxnss[order]->totrxn,reaction);
1836 		LCHECK(r>=0,funcname,ECnonexist,"reaction not found");
1837 		if(orderptr) *orderptr=order-1; }
1838 	return r;
1839  failure:
1840 	return (int)Liberrorcode; }
1841 
1842 
1843 /* smolGetReactionIndexNT */
smolGetReactionIndexNT(simptr sim,int * orderptr,const char * reaction)1844 extern CSTRING int smolGetReactionIndexNT(simptr sim,int *orderptr,const char *reaction) {
1845 	const char *funcname="smolGetReactionIndexNT";
1846 	int order,r;
1847 
1848 	LCHECKNT(sim,funcname,ECmissing,"missing sim");
1849 	LCHECKNT(reaction,funcname,ECmissing,"missing reaction");
1850 	LCHECKNT(strcmp(reaction,"all"),funcname,ECall,"reaction cannot be 'all'");
1851 	if(orderptr && *orderptr>=0 && *orderptr<MAXORDER) {
1852 		order=*orderptr;
1853 		LCHECKNT(sim->rxnss[order] && sim->rxnss[order]->totrxn,funcname,ECnonexist,"no reactions defined of this order");
1854 		r=stringfind(sim->rxnss[order]->rname,sim->rxnss[order]->totrxn,reaction);
1855 		LCHECKNT(r>=0,funcname,ECnonexist,"reaction not found"); }
1856 	else {
1857 		r=-1;
1858 		for(order=0;order<MAXORDER && r<0;order++)
1859 			if(sim->rxnss[order])
1860 				r=stringfind(sim->rxnss[order]->rname,sim->rxnss[order]->totrxn,reaction);
1861 		LCHECKNT(r>=0,funcname,ECnonexist,"reaction not found");
1862 		if(orderptr) *orderptr=order-1; }
1863 	return r;
1864  failure:
1865 	return (int)Liberrorcode; }
1866 
1867 
1868 /* smolGetReactionName */
smolGetReactionName(simptr sim,int order,int reactionindex,char * reaction)1869 extern CSTRING char *smolGetReactionName(simptr sim,int order,int reactionindex,char *reaction) {
1870 	const char *funcname="smolGetReactionName";
1871 
1872 	LCHECK(sim,funcname,ECmissing,"missing sim");
1873 	LCHECK(order>=0 && order<MAXORDER,funcname,ECbounds,"invalid reaction order");
1874 	LCHECK(reactionindex>=0,funcname,ECbounds,"invalid reaction name");
1875 	LCHECK(reaction,funcname,ECmissing,"missing reaction");
1876 	LCHECK(sim->rxnss[order] && sim->rxnss[order]->totrxn,funcname,ECnonexist,"no reactions defined of this order");
1877 	LCHECK(reactionindex<sim->rxnss[order]->totrxn,funcname,ECnonexist,"reaction does not exist");
1878 	strcpy(reaction,sim->rxnss[order]->rname[reactionindex]);
1879 	return reaction;
1880 failure:
1881 	return NULL; }
1882 
1883 
1884 /* smolSetReactionRate */
smolSetReactionRate(simptr sim,const char * reaction,double rate,int isinternal)1885 extern CSTRING enum ErrorCode smolSetReactionRate(simptr sim,const char *reaction,double rate,int isinternal) {
1886 	const char *funcname="smolSetReactionRate";
1887 	int r,er,order;
1888 	rxnptr rxn;
1889 
1890 	LCHECK(sim,funcname,ECmissing,"missing sim");
1891 	order=-1;
1892 	r=smolGetReactionIndexNT(sim,&order,reaction);
1893 	LCHECK(r>=0,funcname,ECsame,NULL);
1894 	rxn=sim->rxnss[order]->rxn[r];
1895 	if(!isinternal)
1896 		er=RxnSetValue(sim,"rate",rxn,rate);
1897 	else if(order<2)
1898 		er=RxnSetValue(sim,"prob",rxn,rate);
1899 	else
1900 		er=RxnSetValue(sim,"bindrad",rxn,rate);
1901 	if(er==3) LCHECK(0,funcname,ECwarning,"rate was set previously");
1902 	else LCHECK(!er,funcname,ECbug,"RxnSetValue error");
1903 	return Libwarncode;
1904  failure:
1905 	return Liberrorcode; }
1906 
1907 
1908 /* smolSetReactionRegion */
smolSetReactionRegion(simptr sim,const char * reaction,const char * compartment,const char * surface)1909 extern CSTRING enum ErrorCode smolSetReactionRegion(simptr sim,const char *reaction,const char *compartment,const char *surface) {
1910 	const char *funcname="smolSetReactionRegion";
1911 	int order,r,c,s;
1912 	rxnptr rxn;
1913 
1914 	LCHECK(sim,funcname,ECmissing,"missing sim");
1915 	order=-1;
1916 	r=smolGetReactionIndexNT(sim,&order,reaction);
1917 	LCHECK(r>=0,funcname,ECsame,NULL);
1918 	rxn=sim->rxnss[order]->rxn[r];
1919 
1920 	if(compartment && compartment[0]!='\0') {
1921 		c=smolGetCompartmentIndexNT(sim,compartment);
1922 		LCHECK(c>=0,funcname,ECsame,NULL);
1923 		RxnSetCmpt(rxn,sim->cmptss->cmptlist[c]); }
1924 	else if(compartment && compartment[0]=='\0')
1925 		RxnSetCmpt(rxn,NULL);
1926 
1927 	if(surface && surface[0]!='\0') {
1928 		s=smolGetSurfaceIndexNT(sim,surface);
1929 		LCHECK(s>=0,funcname,ECsame,NULL);
1930 		RxnSetSurface(rxn,sim->srfss->srflist[s]); }
1931 	else if(surface && surface[0]=='\0')
1932 		RxnSetSurface(rxn,NULL);
1933 
1934 	return ECok;
1935  failure:
1936 	return Liberrorcode; }
1937 
1938 
1939 /* smolSetReactionIntersurface */
smolSetReactionIntersurface(simptr sim,const char * reaction,int * rulelist)1940 enum ErrorCode smolSetReactionIntersurface(
1941     simptr sim, const char *reaction, int *rulelist)
1942 {
1943     const char *funcname = "smolSetReactionIntersurface";
1944     int order, r, i;
1945     int er;
1946     listptrv vlist;
1947     rxnptr rxn = NULL;
1948 
1949     readrxnname(sim, reaction, &order, &rxn, NULL, 1);
1950     if(!rxn)
1951         readrxnname(sim, reaction, &order, &rxn, NULL, 2);
1952     if(!rxn)
1953         readrxnname(sim, reaction, &order, &rxn, NULL, 3);
1954 
1955     LCHECK(rxn, funcname, ECnonexist, NULL);
1956     LCHECK(order == 2, funcname, ECerror, NULL);
1957 
1958     rxn = NULL;
1959     r   = readrxnname(sim, reaction, NULL, &rxn, NULL, 1);
1960     if(r >= 0) {
1961         er = RxnSetIntersurfaceRules(rxn, rulelist);
1962         LCHECK(er != 1, funcname, ECmemory, NULL);
1963     }
1964     r = readrxnname(sim, reaction, NULL, &rxn, &vlist, 2);
1965     LCHECK(r != -2, funcname, ECmemory, NULL);
1966     if(r >= 0) {
1967         for(i = 0; i < vlist->n; i++) {
1968             er = RxnSetIntersurfaceRules((rxnptr)vlist->xs[i], rulelist);
1969             LCHECK(er != 1, funcname, ECmemory, NULL);
1970         }
1971         ListFreeV(vlist);
1972     }
1973     r = readrxnname(sim, reaction, NULL, &rxn, NULL, 3);
1974     LCHECK(r != -2, funcname, ECmemory, NULL);
1975     if(r >= 0) {
1976         er = RxnSetIntersurfaceRules(rxn, rulelist);
1977         LCHECK(er != 1, funcname, ECmemory, NULL);
1978     }
1979 
1980     return ECok;
1981 failure:
1982     return Liberrorcode;
1983 }
1984 
1985 /* smolSetReactionProducts */
smolSetReactionProducts(simptr sim,const char * reaction,enum RevParam method,double parameter,const char * product,double * position)1986 extern CSTRING enum ErrorCode smolSetReactionProducts(simptr sim,const char *reaction,enum RevParam method,double parameter,const char *product,double *position) {
1987 	const char *funcname="smolSetReactionProducts";
1988 	int order,r,done,prd,i,er;
1989 	rxnptr rxn;
1990 
1991 	LCHECK(sim,funcname,ECmissing,"missing sim");
1992 	order=-1;
1993 	r=smolGetReactionIndexNT(sim,&order,reaction);
1994 	LCHECK(r>=0,funcname,ECsame,NULL);
1995 	rxn=sim->rxnss[order]->rxn[r];
1996 
1997 	prd=-1;
1998 	if(product && strlen(product)>0) {
1999 		i=smolGetSpeciesIndexNT(sim,product);
2000 		LCHECK(i>0,funcname,ECsame,NULL);
2001 		done=0;
2002 		for(prd=0;prd<rxn->nprod && !done;prd++)
2003 			if(rxn->prdident[prd]==i) done=1;
2004 		prd--;
2005 		LCHECK(done,funcname,ECerror,"listed product is not a product of the listed reaction"); }
2006 
2007 	er=RxnSetRevparam(sim,rxn,method,parameter,prd,position,sim->dim);
2008 	LCHECK(er!=1,funcname,ECwarning,"reaction product parameter was set before");
2009 	LCHECK(er!=2,funcname,ECbounds,"reaction product parameter out of bounds");
2010 	LCHECK(er!=3,funcname,ECnonexist,"invalid reaction product method");
2011 	LCHECK(er!=4,funcname,ECmissing,"missing product name");
2012 	LCHECK(er!=5,funcname,ECmissing,"missing product position");
2013 
2014 	return Libwarncode;
2015 failure:
2016 	return Liberrorcode; }
2017 
2018 
2019 
2020 /******************************************************************************/
2021 /*********************************** Ports ************************************/
2022 /******************************************************************************/
2023 
2024 /* smolAddPort */
smolAddPort(simptr sim,const char * port,const char * surface,enum PanelFace face)2025 extern CSTRING enum ErrorCode smolAddPort(simptr sim,const char *port,const char *surface,enum PanelFace face) {
2026 	const char *funcname="smolAddPort";
2027 	int s;
2028 	portptr simport;
2029 
2030 	LCHECK(sim,funcname,ECmissing,"missing sim");
2031 	LCHECK(port,funcname,ECmissing,"missing port");
2032 	s=smolGetSurfaceIndexNT(sim,surface);
2033 	if(s==(int)ECmissing) smolClearError();
2034 	else LCHECK(s>=0,funcname,ECsame,NULL);
2035 	LCHECK(face==PFfront || face==PFback || face==PFnone,funcname,ECsyntax,"invalid face");
2036 	simport=portaddport(sim,port,sim->srfss->srflist[s],face);
2037 	LCHECK(simport,funcname,ECmemory,"out of memory adding port");
2038 
2039 	return ECok;
2040  failure:
2041 	return Liberrorcode; }
2042 
2043 
2044 /* smolGetPortIndex */
smolGetPortIndex(simptr sim,const char * port)2045 extern CSTRING int smolGetPortIndex(simptr sim,const char *port) {
2046 	const char *funcname="smolGetPortIndex";
2047 	int p;
2048 
2049 	LCHECK(sim,funcname,ECmissing,"missing sim");
2050 	LCHECK(port,funcname,ECmissing,"missing port");
2051 	LCHECK(sim->portss && sim->portss->nport,funcname,ECnonexist,"no ports defined");
2052 	LCHECK(strcmp(port,"all"),funcname,ECall,"port cannot be 'all'");
2053 	p=stringfind(sim->portss->portnames,sim->portss->nport,port);
2054 	LCHECK(p>=0,funcname,ECnonexist,"port not found");
2055 	return p;
2056  failure:
2057 	return (int)Liberrorcode; }
2058 
2059 
2060 /* smolGetPortIndexNT */
smolGetPortIndexNT(simptr sim,const char * port)2061 extern CSTRING int smolGetPortIndexNT(simptr sim,const char *port) {
2062 	const char *funcname="smolGetPortIndexNT";
2063 	int p;
2064 
2065 	LCHECKNT(sim,funcname,ECmissing,"missing sim");
2066 	LCHECKNT(port,funcname,ECmissing,"missing port");
2067 	LCHECKNT(sim->portss && sim->portss->nport,funcname,ECnonexist,"no ports defined");
2068 	LCHECKNT(strcmp(port,"all"),funcname,ECall,"port cannot be 'all'");
2069 	p=stringfind(sim->portss->portnames,sim->portss->nport,port);
2070 	LCHECKNT(p>=0,funcname,ECnonexist,"port not found");
2071 	return p;
2072  failure:
2073 	return (int)Liberrorcode; }
2074 
2075 
2076 /* smolGetPortName */
smolGetPortName(simptr sim,int portindex,char * port)2077 extern CSTRING char *smolGetPortName(simptr sim,int portindex,char *port) {
2078 	const char *funcname="smolGetPortName";
2079 
2080 	LCHECK(sim,funcname,ECmissing,"missing sim");
2081 	LCHECK(portindex>=0,funcname,ECbounds,"invalid port index");
2082 	LCHECK(port,funcname,ECmissing,"missing port string");
2083 	LCHECK(sim->portss && sim->portss->nport,funcname,ECnonexist,"no ports defined");
2084 	LCHECK(portindex<sim->portss->nport,funcname,ECnonexist,"port does not exist");
2085 	strcpy(port,sim->portss->portnames[portindex]);
2086 	return port;
2087  failure:
2088 	return NULL; }
2089 
2090 
2091 /* smolAddPortMolecules */
smolAddPortMolecules(simptr sim,const char * port,int nmolec,const char * species,double ** positions)2092 extern CSTRING enum ErrorCode smolAddPortMolecules(simptr sim,const char *port,int nmolec,const char *species,double **positions) {
2093 	const char *funcname="smolAddPortMolecules";
2094 	int prt,i,er;
2095 	portptr simport;
2096 
2097 	LCHECK(sim,funcname,ECmissing,"missing sim");
2098 	prt=smolGetPortIndexNT(sim,port);
2099 	LCHECK(prt>=0,funcname,ECsame,NULL);
2100 	simport=sim->portss->portlist[prt];
2101 	if(nmolec==0) return ECok;
2102 	LCHECK(nmolec>0,funcname,ECbounds,"nmolec cannot be negative");
2103 	i=smolGetSpeciesIndexNT(sim,species);
2104 	LCHECK(i>0,funcname,ECsame,NULL);
2105 	er=portputmols(sim,simport,nmolec,i,NULL,positions,NULL);
2106 	LCHECK(er!=1,funcname,ECmemory,"out of memory");
2107 	LCHECK(er!=2,funcname,ECnonexist,"no porting surface defined");
2108 	LCHECK(er!=3,funcname,ECnonexist,"no porting face defined");
2109 	LCHECK(er!=4,funcname,ECnonexist,"no panels on porting surface");
2110 
2111 	return ECok;
2112 failure:
2113 	return Liberrorcode; }
2114 
2115 
2116 /* smolGetPortMolecules */
smolGetPortMolecules(simptr sim,const char * port,const char * species,enum MolecState state,int remove)2117 extern CSTRING int smolGetPortMolecules(simptr sim,const char *port,const char *species,enum MolecState state,int remove) {
2118 	const char *funcname="smolGetPortMolecules";
2119 	int prt,i,num;
2120 	portptr simport;
2121 
2122 	LCHECK(sim,funcname,ECmissing,"missing sim");
2123 	prt=smolGetPortIndexNT(sim,port);
2124 	LCHECK(prt>=0,funcname,ECsame,NULL);
2125 	simport=sim->portss->portlist[prt];
2126 
2127 	i=smolGetSpeciesIndexNT(sim,species);
2128 	if(i==(int)ECall) {smolClearError();i=-5;}
2129 	else LCHECK(i>0,funcname,ECsame,NULL);
2130 	LCHECK((state>=0 && state<MSMAX) || state==MSall,funcname,ECsyntax,"invalid state");
2131 
2132 	num=portgetmols(sim,simport,i,state,remove);
2133 	return num;
2134 failure:
2135 	return (int)Liberrorcode; }
2136 
2137 
2138 
2139 /******************************************************************************/
2140 /*********************************** Lattices *********************************/
2141 /******************************************************************************/
2142 
2143 /* smolAddLattice */
smolAddLattice(simptr sim,const char * lattice,const double * min,const double * max,const double * dx,const char * btype)2144 extern CSTRING enum ErrorCode smolAddLattice(simptr sim,const char *lattice,const double *min,const double *max,const double *dx,const char *btype) {
2145 	const char *funcname="smolAddLattice";
2146 	int er,p;
2147 	latticeptr simlattice;
2148 	simlattice = NULL;
2149 	LCHECK(sim,funcname,ECmissing,"missing sim");
2150 	LCHECK(lattice,funcname,ECmissing,"missing lattice");
2151 	p=stringfind(sim->latticess->latticenames,sim->latticess->nlattice,lattice);
2152 	LCHECK(p<0,funcname,ECsame,"lattice name already exists");
2153 	er=latticeaddlattice(sim,&simlattice,lattice,min,max,dx,btype,LATTICEnsv);
2154 	LCHECK(er==0,funcname,ECerror,"error adding lattice");
2155 	LCHECK(simlattice,funcname,ECmemory,"out of memory adding lattice");
2156 	return ECok;
2157  failure:
2158 	return Liberrorcode;
2159 }
2160 
2161 
2162 /* smolGetLatticeIndex */
smolGetLatticeIndex(simptr sim,const char * lattice)2163 extern CSTRING int smolGetLatticeIndex(simptr sim,const char *lattice) {
2164 	const char *funcname="smolGetLatticeIndex";
2165 	int p;
2166 
2167 	LCHECK(sim,funcname,ECmissing,"missing sim");
2168 	LCHECK(lattice,funcname,ECmissing,"missing lattice");
2169 	LCHECK(sim->latticess && sim->latticess->nlattice,funcname,ECnonexist,"no lattices defined");
2170 	LCHECK(strcmp(lattice,"all"),funcname,ECall,"lattice cannot be 'all'");
2171 	p=stringfind(sim->latticess->latticenames,sim->latticess->nlattice,lattice);
2172 	LCHECK(p>=0,funcname,ECnonexist,"lattice not found");
2173 	return p;
2174  failure:
2175 	return (int)Liberrorcode; }
2176 
2177 
2178 /* smolGetLatticeIndexNT */
smolGetLatticeIndexNT(simptr sim,const char * lattice)2179 extern CSTRING int smolGetLatticeIndexNT(simptr sim,const char *lattice) {
2180 	const char *funcname="smolGetLatticeIndexNT";
2181 	int p;
2182 
2183 	LCHECKNT(sim,funcname,ECmissing,"missing sim");
2184 	LCHECKNT(lattice,funcname,ECmissing,"missing lattice");
2185 	LCHECKNT(sim->latticess && sim->latticess->nlattice,funcname,ECnonexist,"no lattices defined");
2186 	LCHECKNT(strcmp(lattice,"all"),funcname,ECall,"lattice cannot be 'all'");
2187 	p=stringfind(sim->latticess->latticenames,sim->latticess->nlattice,lattice);
2188 	LCHECKNT(p>=0,funcname,ECnonexist,"lattice not found");
2189 	return p;
2190  failure:
2191 	return (int)Liberrorcode; }
2192 
2193 
2194 /* smolGetLatticeName */
smolGetLatticeName(simptr sim,int latticeindex,char * lattice)2195 extern CSTRING char *smolGetLatticeName(simptr sim,int latticeindex,char *lattice) {
2196 	const char *funcname="smolGetLatticeName";
2197 
2198 	LCHECK(sim,funcname,ECmissing,"missing sim");
2199 	LCHECK(latticeindex>=0,funcname,ECbounds,"invalid lattice index");
2200 	LCHECK(lattice,funcname,ECmissing,"missing lattice string");
2201 	LCHECK(sim->latticess && sim->latticess->nlattice,funcname,ECnonexist,"no lattices defined");
2202 	LCHECK(latticeindex<sim->latticess->nlattice,funcname,ECnonexist,"lattice does not exist");
2203 	strcpy(lattice,sim->latticess->latticenames[latticeindex]);
2204 	return lattice;
2205  failure:
2206 	return NULL; }
2207 
2208 /* smolAddLatticeMolecules */
smolAddLatticeMolecules(simptr sim,const char * lattice,const char * species,int number,double * lowposition,double * highposition)2209 extern CSTRING enum ErrorCode smolAddLatticeMolecules(simptr sim,const char *lattice, const char *species,int number,double *lowposition,double *highposition) {
2210 	const char *funcname="smolAddLatticeMolecules";
2211 	int er,i,lat;
2212 	double *low,*high;
2213 	latticeptr simlattice;
2214 
2215 	LCHECK(sim,funcname,ECmissing,"missing sim");
2216 	lat=smolGetLatticeIndexNT(sim,lattice);
2217 	LCHECK(lat>=0,funcname,ECsame,NULL);
2218 	simlattice=sim->latticess->latticelist[lat];
2219 	if(number==0) return ECok;
2220 	LCHECK(number>0,funcname,ECbounds,"nmolec cannot be negative");
2221 	i=smolGetSpeciesIndexNT(sim,species);
2222 	LCHECK(i>0,funcname,ECsame,NULL);
2223 	LCHECK(number>=0,funcname,ECbounds,"number cannot be < 0");
2224 	if(!lowposition)
2225 		low = simlattice->min;
2226 	else
2227 		low=lowposition;
2228 	if(!highposition)
2229 		high = simlattice->max;
2230 	else
2231 		high=highposition;
2232 	er=latticeaddmols(simlattice,number,i,low,high,sim->dim);
2233 	LCHECK(!er,funcname,ECmemory,"out of memory adding molecules");
2234 	return ECok;
2235  failure:
2236 	return Liberrorcode; }
2237 
2238 /* smolAddLatticePort */
smolAddLatticePort(simptr sim,const char * lattice,const char * port)2239 extern CSTRING enum ErrorCode smolAddLatticePort(simptr sim, const char *lattice, const char *port) {
2240 	const char *funcname="smolAddLatticePort";
2241 	int prt,lat;
2242 	latticeptr simlattice;
2243 	portptr simport;
2244 
2245 	LCHECK(sim,funcname,ECmissing,"missing sim");
2246 	lat=smolGetLatticeIndexNT(sim,lattice);
2247 	LCHECK(lat>=0,funcname,ECsame,NULL);
2248 	simlattice=sim->latticess->latticelist[lat];
2249 	prt=smolGetPortIndexNT(sim,port);
2250 	LCHECK(prt>=0,funcname,ECsame,NULL);
2251 	simport=sim->portss->portlist[prt];
2252 	latticeaddport(simlattice,simport);
2253 	return ECok;
2254  failure:
2255 	return Liberrorcode; }
2256 
2257 
2258 /* smolAddLatticeSpecies */
smolAddLatticeSpecies(simptr sim,const char * lattice,const char * species)2259 extern CSTRING enum ErrorCode smolAddLatticeSpecies(simptr sim,const char *lattice, const char *species) {
2260 	const char *funcname="smolAddLatticeSpecies";
2261 	int er,i,lat;
2262 	latticeptr simlattice;
2263 
2264 	LCHECK(sim,funcname,ECmissing,"missing sim");
2265 	lat=smolGetLatticeIndexNT(sim,lattice);
2266 	LCHECK(lat>=0,funcname,ECsame,NULL);
2267 	simlattice=sim->latticess->latticelist[lat];
2268 	i=smolGetSpeciesIndexNT(sim,species);
2269 	LCHECK(i>0,funcname,ECsame,NULL);
2270 	er=latticeaddspecies(simlattice,i,NULL);
2271 	LCHECK(!er,funcname,ECmemory,"out of memory in latticeaddspecies");
2272 	return ECok;
2273  failure:
2274 	return Liberrorcode; }
2275 
2276 /* smolAddLatticeReaction */
smolAddLatticeReaction(simptr sim,const char * lattice,const char * reaction,const int move)2277 extern CSTRING enum ErrorCode smolAddLatticeReaction(simptr sim,const char *lattice, const char *reaction, const int move) {
2278 	const char *funcname="smolAddLatticeReaction";
2279 	int er,lat,r,order;
2280 	latticeptr simlattice;
2281 	rxnptr rxn;
2282 
2283 	LCHECK(sim,funcname,ECmissing,"missing sim");
2284 	lat=smolGetLatticeIndexNT(sim,lattice);
2285 	LCHECK(lat>=0,funcname,ECsame,NULL);
2286 	simlattice=sim->latticess->latticelist[lat];
2287 	order=-1;
2288 	r=smolGetReactionIndexNT(sim,&order,reaction);
2289 	LCHECK(r>=0,funcname,ECsame,NULL);
2290 	rxn=sim->rxnss[order]->rxn[r];
2291 
2292 	er=latticeaddrxn(simlattice,rxn,move);
2293 	LCHECK(!er,funcname,ECmemory,"out of memory in latticeaddrxn");
2294 	return ECok;
2295  failure:
2296 	return Liberrorcode; }
2297