bump to -rc12
[gnucap-felix.git] / modules / s_sock.cc
blobd501eface4e2a91414238c5f5779ddaa9efbe44f
1 /* Copyright (C) 2011-2013 Felix Salfelder, Lars Hedrich
2 * Author: Felix Salfelder
4 * This file is part of "Gnucap", the Gnu Circuit Analysis Package
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3, or (at your option)
9 * any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * 02110-1301, USA.
20 *------------------------------------------------------------------
21 * a remote control socket. used by verification tools
23 #include "globals.h"
24 #include "u_status.h"
25 #include <unistd.h>
26 #include "u_prblst.h"
27 #include "u_cardst.h"
28 #include "u_nodemap.h"
29 #include "e_elemnt.h"
30 #include "e_storag.h"
31 #include "e_subckt.h"
32 #include "d_subckt.h"
33 #include "u_sock.h"
34 #include "s_ddc.h"
35 #include "io_error.h"
36 #include "resolv.h"
37 #include "s__.h"
38 #include "io_matrix.h"
39 #include "m_matrix_extra.h"
40 #include <iomanip>
41 #include "d_cap.h"
42 #include <fcntl.h>
43 /*--------------------------------------------------------------------------*/
44 #define userinfo( a,b,c,d,e,f )
45 /*--------------------------------------------------------------------------*/
46 using namespace std;
47 using namespace SOME_CAP_HACK; // FIXME. (maybe use STORAGE device interface?)
48 /*--------------------------------------------------------------------------*/
49 namespace {
50 /*--------------------------------------------------------------------------*/
51 typedef union {
52 double double_val;
53 int32_t int_val;
54 } di_union_t;
56 /*--------------------------------------------------------------------------*/
57 class SOCK : public DDC_BASE {
58 public:
59 explicit SOCK();
60 ~SOCK();
61 string status()const;
62 protected:
63 void options(CS&, int x=0);
64 private:
65 void sweep();
66 void sweep_recursive(int);
67 void first(int);
68 bool next(int);
69 void send_matrix();
70 void undo_time_step();
71 void tr_reject();
72 static unsigned tr_steps_rejected_;
73 protected:
74 enum {DCNEST = 4};
75 int _n_sweeps;
76 // typedef void (*p)(double);
77 //ELEMENT* (_pushel[DCNEST]); /* pointer to thing to sweep, dc command */
78 CARDSTASH _stash[DCNEST]; /* store std values of elements being swept */
79 bool _loop[DCNEST]; /* flag: do it again backwards */
80 bool _reverse_in[DCNEST]; /* flag: sweep backwards, input */
81 bool _reverse[DCNEST]; /* flag: sweep backwards, working */
82 bool _cont; /* flag: continue from previous run */
83 TRACE _trace; /* enum: show extended diagnostics */
84 enum {ONE_PT, LIN_STEP, LIN_PTS, TIMES, OCTAVE, DECADE} _stepmode[DCNEST];
85 static double temp_c_in; /* ambient temperature, input and sweep variable */
86 bool _dump_matrix;
87 unsigned port;
88 double* U;
89 double* CU;
90 double* CUTCU;
91 public:
92 void do_it(CS&, CARD_LIST*);
93 private:
94 void setup(CS&);
95 void fillnames( const CARD_LIST* scope);
96 void findcaps( CARD_LIST* scope);
97 void cap_prepare();
98 void cap_reset();
99 vector<string> var_namen_arr;
100 vector<COMPONENT*> _caplist; // FIXME: use cardlist
101 CARDSTASH* _capstash;
102 uint16_t var_namen_total_size;
104 private: //vera stuff.
105 void main_loop();
106 void verainit(unsigned, unsigned, unsigned);
107 void verakons();
108 void veraop();
109 void verainit_reply();
110 void verakons_reply();
111 void veraop_reply();
112 void ev_iter();
113 void set_param();
114 unsigned transtep(unsigned init, double dt);
115 void transtep_reply(unsigned, bool eol=true);
116 void transtep_gc_reply(unsigned);
118 char* var_names_buf;
120 unsigned _verbose;
121 size_t total;
122 size_t n_inputs() const{return _input_names.size();}
123 vector<string> _input_names;
124 vector<ELEMENT*> _input_devs;
125 unsigned n_vars;
126 unsigned n_vars_square;
127 uint16_t n_eingaenge;
128 uint16_t length;
130 SocketStream stream;
131 //unsigned BUFSIZE;
132 unsigned n_bytes;
134 uint16_t _error; // transport between method and method_reply
135 double _dthack; // same
137 double *dc_werteA,*dc_loesungA,*kons_loesungA,*kons_residuumA;
139 int channel;
140 int frame_number;
141 Socket* socket;
142 short unsigned _port_range;
143 string _port; // kommt ueber die Uebergabeparamter port
144 // globale Variable daher (default: port=1400)
145 bool _client_mode;
146 bool _server_mode;
147 unsigned _bufsize;
148 bool _bigarg;
149 bool _binout;
150 string _host;
151 int reuseaddr;
152 struct sockaddr_in sin;
154 double *matrixg, *matrixc,*vectorq;
156 static const int printlevel=0;
159 /*--------------------------------------------------------------------------*/
160 unsigned SOCK::tr_steps_rejected_ = 0;
161 double SOCK::temp_c_in = 0.;
162 /*--------------------------------------------------------------------------*/
163 void SOCK::do_it(CS& Cmd, CARD_LIST* Scope)
165 trace0("SOCK::do_it");
166 IO::error.detach(stdout);
167 IO::error.attach(stderr);
168 _scope = Scope;
169 _sim->_time0 = 0.;
170 //_sim->set_command_ddc();
171 _sim->set_command_dc();
172 _sim->_phase = p_INIT_DC;
173 //_sim->_ddc = true;
174 ::status.ddc.reset().start();
175 _sim->_temp_c = temp_c_in;
176 _dump_matrix = 0;
177 reuseaddr = 0;
178 _port = "1400";
179 _port_range = 1;
180 _client_mode = false;
181 _host = "localhost";
183 command_base(Cmd);
185 //cleanup
186 cap_reset();
188 /*--------------------------------------------------------------------------*/
189 SOCK::SOCK() :DDC_BASE(),
190 _n_sweeps(1),
191 _cont(false),
192 _trace(tNONE)
195 for (int ii = 0; ii < DCNEST; ++ii) {
196 _loop[ii] = false;
197 _reverse_in[ii] = false;
198 _reverse[ii] = false;
199 _step[ii] = 0.;
200 _linswp[ii] = true;
201 _zap[ii]=NULL;
202 _stepmode[ii] = ONE_PT;
204 temp_c_in=OPT::temp_c;
205 _out=IO::mstdout;
207 /*--------------------------------------------------------------------------*/
208 void SOCK::setup(CS& Cmd)
210 _sim->_uic = false;
211 trace0("SOCK::setup");
212 _cont = false;
213 _trace = tNONE;
214 _out = IO::mstdout;
215 _out.reset(); //BUG// don't know why this is needed */
216 bool ploton = IO::plotset && plotlist().size() > 0;
218 options(Cmd);
220 if (Cmd.more()) {
221 }else{
223 Cmd.check(bWARNING, "what's this?");
225 _sim->_uic = true;
226 CKT_BASE::_sim->init();
228 IO::plotout = (ploton) ? IO::mstdout : OMSTREAM();
229 initio(_out);
231 _error = 0; /* verainit(v_flag, n_inputs, &n_vars, charbuf, &length); */
232 n_vars = static_cast<uint16_t>( _sim->_total_nodes) ; // _sim->total_nodes doesnt include gnd
233 // do this also in sweep to initialize the socket streaM
234 var_namen_arr.resize( n_vars, string("unset"));
235 // var_namen_arr[0]="0";
236 fillnames( &CARD_LIST::card_list );
237 n_vars_square = n_vars * n_vars;
239 findcaps(&CARD_LIST::card_list);
241 // BUG! this kills cap bm's
242 cap_prepare(); // attach value common if !has_common. stash old common
244 #ifndef NDEBUG
245 for (unsigned i=0; i < n_vars; i++)
246 trace0("name: " + var_namen_arr[i]);
247 #endif
249 assert(_n_sweeps > 0);
250 _sim->_freq = 0;
252 // not implemented. need to queue sources properly (CARDLIST::q_hack..?)
253 if(OPT::prequeue) { // incomplete();
254 error(bDANGER, "prequeueing is experimental, this might not work\n");
255 OPT::prequeue=false;
256 }else{
259 /*--------------------------------------------------------------------------*/
260 void SOCK::options(CS& Cmd, int Nest)
262 trace0("SOCK::options... ");
264 _sim->_uic = _loop[Nest] = _reverse_in[Nest] = false;
265 _port = "1400";
266 _bufsize = BUFSIZE;
267 _bigarg = true;
268 _binout = true;
269 unsigned here = Cmd.cursor();
271 ONE_OF
272 || (Cmd.match1("'\"({") && ((Cmd >> _step_in[Nest]), (_stepmode[Nest] = LIN_STEP)))
273 || (Cmd.is_float() && ((Cmd >> _step_in[Nest]), (_stepmode[Nest] = LIN_STEP)))
274 || (Get(Cmd, "*", &_step_in[Nest]) && (_stepmode[Nest] = TIMES))
275 || (Get(Cmd, "+", &_step_in[Nest]) && (_stepmode[Nest] = LIN_STEP))
276 || Get(Cmd, "b{ufsize}", &_bufsize)
277 || Get(Cmd, "c{ontinue}", &_cont)
278 || Get(Cmd, "port" , &_port)
279 || Get(Cmd, "listen{port}", &_port)
280 || Get(Cmd, "bigarg", &_bigarg)
281 || Get(Cmd, "binout", &_binout)
282 || Get(Cmd, "host" , &_host)
283 || Get(Cmd, "tr{s}", &_do_tran_step)
284 || Get(Cmd, "dm", &_dump_matrix)
285 || Get(Cmd, "client", &_client_mode)
286 || Get(Cmd, "server", &_server_mode)
287 || Get(Cmd, "dt{emp}", &temp_c_in, mOFFSET, OPT::temp_c)
288 || Get(Cmd, "lo{op}", &_loop[Nest])
289 || Get(Cmd, "re{verse}", &_reverse_in[Nest])
290 || Get(Cmd, "te{mperature}",&temp_c_in)
291 || (Cmd.umatch("tr{ace} {=}") &&
292 (ONE_OF
293 || Set(Cmd, "n{one}", &_trace, tNONE)
294 || Set(Cmd, "o{ff}", &_trace, tNONE)
295 || Set(Cmd, "w{arnings}", &_trace, tUNDER)
296 || Set(Cmd, "i{terations}",&_trace, tITERATION)
297 || Set(Cmd, "v{erbose}", &_trace, tVERBOSE)
298 || Cmd.warn(bWARNING,
299 "need none, off, warnings, iterations, verbose")
302 || _out.outset(Cmd);
303 }while (Cmd.more() && !Cmd.stuck(&here));
305 /*--------------------------------------------------------------------------*/
306 static void register_status();
307 /*--------------------------------------------------------------------------*/
308 void SOCK::sweep()
310 register_status();
311 // later... FIXME
313 frame_number = 0;
314 n_bytes = 0;
315 trace1("SOCK::do_it", _port);
317 // Calculate buffersize
318 n_vars = _sim->_total_nodes;
319 // _sim->total_nodes doesnt include gnd
320 n_vars_square = n_vars * n_vars;
321 _bufsize = n_vars_square * 3 * (unsigned)sizeof(double) + 32;
322 // 3 quadratic matrices * doubles + some safety margin (BUG)
324 if (_client_mode){
325 trace1("bufsize Client ", _bufsize);
326 socket = new ClientSocket(Socket::TCP, _port, _host, _bufsize);
327 trace1("connected to "+ _host, _port );
328 stream = *socket;
329 } else if (_server_mode) {
330 stringstream p(_port);
331 uint16_t _port_;
332 p >> _port_;
333 trace1("bufsize Server ", _bufsize);
334 socket = new ServerSocket(Socket::TCP, _port_, 1u, _bufsize);
335 ServerSocket* sock=prechecked_cast<ServerSocket*>(socket);
337 trace0("SOCK::do_it waiting");
338 stream = sock->listen();
339 } else {
340 fflush( stdout );
341 fflush( stdin );
342 trace0("SOCK::sweep simple i/o");
343 socket=0;
344 trace1("bufsize Stdin ", _bufsize);
345 if (!_binout) {
346 int devnull=open("/dev/null",O_WRONLY);
347 trace2("Socket stream for dev null" ,devnull, STDIN_FILENO);
348 stream = SocketStream( devnull, STDIN_FILENO, _bufsize);
349 } else {
350 stream = SocketStream( STDOUT_FILENO, STDIN_FILENO, _bufsize);
352 stream << "gnucap sock ready";
355 main_loop();
356 delete socket;
357 return;
359 /*--------------------------------------------------------------------------*/
360 string SOCK::status()const
362 // incomplete();
363 return "sock: tr rejected=" + ::to_string(tr_steps_rejected_) + "\n";
365 /*--------------------------------------------------------------------------*/
366 // void SOCK::sweep_recursive(int )
367 // {
368 // assert(false);
369 // }
370 /*--------------------------------------------------------------------------*/
371 // fetch names from circuit recursively. fill into local vector.
372 void SOCK::fillnames( const CARD_LIST* scope){
373 trace0("SOCK::fillnames");
375 const NODE_MAP * nm = scope->nodes();
376 for (NODE_MAP::const_iterator i = nm->begin(); i != nm->end(); ++i) {
377 if (i->first != "0") {
378 if (const NODE* a= dynamic_cast<const NODE*>(i->second)){
379 stringstream s;
380 string myname(a->long_label());
381 var_namen_arr[a->matrix_number()-1] = myname;
382 var_namen_total_size = static_cast<uint16_t>( var_namen_total_size + static_cast<uint16_t>(myname.length()) + 1 );
384 }else{
388 for (CARD_LIST::const_iterator i = scope->begin(); i != scope->end(); ++i) {
389 if(const COMPONENT* s = dynamic_cast<const COMPONENT*>(*i)){
390 if (!s->is_device()){
391 }else if ( s->subckt() ) {
392 fillnames( s->subckt() );
394 }else{
398 /*--------------------------------------------------------------------------*/
399 void SOCK::findcaps( CARD_LIST* scope){
400 for (CARD_LIST::iterator i = scope->begin(); i != scope->end(); ++i) {
401 if ( COMPONENT* c = dynamic_cast< COMPONENT*>(*i) ) {
402 if (c->is_device() && c->has_memory()){
403 trace1("found cap", c->long_label());
404 _caplist.push_back( c );
407 if (!(*i)->is_device()){
408 } else if ( BASE_SUBCKT* s = dynamic_cast< BASE_SUBCKT*>(*i) ) {
409 trace1("going down", s->long_label());
410 findcaps( s->subckt() );
414 /*--------------------------------------------------------------------------*/
415 static SOCK p2;
416 static DISPATCHER<CMD>::INSTALL d2(&command_dispatcher, "sock", &p2);
417 /*--------------------------------------------------------------------------*/
418 static void register_status()
420 static bool done;
422 if(!done) {
423 new DISPATCHER<CKT_BASE>::INSTALL(&status_dispatcher, "sock", &p2);
424 done = true;
425 }else{ untested();
428 /*--------------------------------------------------------------------------*/
430 /*--------------------------------------------------------------------------*/
431 static unsigned argc(unsigned opcode)
433 switch(opcode){
434 case 51:
435 return 3;
436 case 52: itested();
437 return 0;
438 case 53:
439 return 0;
440 case 104: itested();
441 case 102:
442 return 1;
443 default:
444 return 0;
447 /*--------------------------------------------------------------------------*/
448 void SOCK::main_loop()
450 trace0("SOCK::main_loop");
452 uint16_t opcode=-1;
453 uint16_t arg[3];
454 unsigned char tmp;
455 arg[0] = -1;
456 bool init_done=false;
458 while(true) {
459 trace0("SOCK::main_loop waiting for opcode");
461 if(_bigarg){
462 stream >> tmp >> 7; // sic!
463 opcode = tmp;
464 for(unsigned i=0; i<argc(opcode); ++i){
465 stream >> arg[i] >> 6;
467 }else{
468 stream >> opcode;
469 stream >> arg[0];
470 stream >> arg[1];
471 stream >> arg[2];
474 _sim->_mode = s_SOCK; // nonsense.
475 // use respective built-in mode!
477 if(_bigarg) {
478 ::error(bDEBUG, "sock opcode %d\n", opcode);
479 }else{
480 ::error(bDEBUG, "sock opcode %d %d %d %d\n", opcode, arg[0], arg[1], arg[2]);
483 double dt;
484 unsigned status;
485 switch (opcode) {
486 case '\0': // 0
487 return;
488 break;
489 case '3': // 51
490 if(init_done) throw Exception("init twice??");
491 verainit(arg[0], arg[1], arg[2]);
492 verainit_reply();
493 init_done=true;
494 break;
495 case '4': // 52
496 veraop();
497 veraop_reply();
498 break;
499 case '5': // 53
500 verakons();
501 verakons_reply();
502 break;
503 case 101: untested();
504 ev_iter();
505 break;
506 case 102:
507 stream >> dt;
508 status = transtep(arg[0], dt);
509 transtep_reply(status);
510 break;
511 case 103: itested();
512 set_param();
513 break;
514 case 104: itested();
515 stream >> dt;
516 status = transtep(arg[0], dt);
517 transtep_gc_reply(status);
518 break;
519 default:
520 ::error(bDANGER, "unknown opcode %i\n", opcode);
521 throw Exception("unknown opcode");
522 break;
524 _sim->reset_iteration_counter(iPRINTSTEP); // used by solve_with_homotopy
525 // reset in outdata (not called)
528 /*--------------------------------------------------------------------------*/
529 // very clever way to transfer strings.
530 static void putstring8(SocketStream* s, const string x)
532 const char* A = x.c_str();
534 while(*A){
535 *s<<*A<<*A<<*A<<*A<<*A<<*A<<*A<<*A;
536 A++;
539 /*--------------------------------------------------------------------------*/
540 void SOCK::verainit(unsigned verbose, unsigned n_in, unsigned length)
542 _verbose = verbose;
543 char input_namen[length+1];
544 unsigned here =0;
545 unsigned n=0;
547 _input_names.resize(n_in);
548 _input_devs.resize(n_in);
549 trace3("verainit: ", verbose,n_inputs(),length);
550 assert(n_inputs()==n_in);
552 for (unsigned i=0; i < length; i++) {
553 stream >> input_namen[i] >> 7;
554 if(input_namen[i] == '\t'){
555 input_namen[i] = 0;
556 trace1("input_namen", string(input_namen+here));
557 trace5("input_namen",input_namen[i-2],input_namen[i-1], input_namen[i-0],here,i );
558 _input_names[n] = string(input_namen+here);
559 here = i+1;
561 trace1("looking out for", _input_names[n]);
562 CARD_LIST::fat_iterator ci = findbranch(_input_names[n], &CARD_LIST::card_list);
563 if (ci.is_end()){
564 throw Exception("cannot find voltage source \"" + _input_names[n] +"\", giving up");
566 trace0("found input device");
567 ELEMENT* d = prechecked_cast<ELEMENT*>(*ci);
568 if (!d){
569 throw Exception("not something we can use as source, \"" + _input_names[n] +"\", giving up");
571 _input_devs[n] = d;
572 assert(_input_devs[n]);
574 unsigned ii=n;
575 // see s_cd. FIXME: revert.
576 _stash[ii] = _input_devs[ii];
577 _input_devs[ii]->inc_probes();
578 _input_devs[ii]->set_value(_input_devs[ii]->value(),0);
579 _input_devs[ii]->set_constant(false); // <= insufficient for PREQEUE
581 ++n;
585 //trace0("input_namen " + string(input_namen) );
586 total = (unsigned) (length+4);
587 assert(stream.bufsize() >= total);
589 assert(!var_names_buf);
590 var_names_buf = (char*) malloc( n_vars * 128 * sizeof(char));
591 strcpy(var_names_buf,"");
592 for (unsigned i=0; i < n_vars; i++)
594 trace1("SOCK::verainit ", var_namen_arr[i]);
595 strcat(var_names_buf, var_namen_arr[i].c_str());
596 strcat(var_names_buf, "\t");
598 //length = static_cast<uint16_t>( strlen(var_names_buf) );
599 // userinfo(1,"vera_titan_ak","Variablennamen %s\n",var_names_buf);
601 /*--------------------------------------------------------------------------*/
602 void SOCK::veraop()
604 trace1("SOCK::veraop",n_vars);
605 total = n_vars;
606 _sim->set_command_dc();
607 assert(stream.bufsize() >= total);
609 dc_werteA = (double*) malloc(sizeof(double)*n_vars);
610 trace1("fetching ",n_vars);
611 assert(_sim->vdc()[0] == 0 );
612 for (unsigned i=0; i < n_inputs(); i++) {
613 double d;
614 stream >> d;
615 trace3("SOCK::veraop setting input", _input_devs[i]->long_label(), i, d);
616 _input_devs[i]->set_value(d);
619 _error = 0; /* veraop(sweep_val, x_new, G, C); */
621 // ================do_dc========
622 _sim->_uic = false;
623 _sim->_bypass_ok = false;
624 _sim->set_inc_mode_bad();
625 OPT::ITL itl = OPT::DCBIAS;
626 _sim->_phase = p_INIT_DC;
628 trace2("SOCK::veraop homotopy", _sim->_phase, _sim->_mode);
629 if(_dump_matrix) {
630 _trace=tVERBOSE;
632 CARD_LIST::card_list.tr_begin(); // hier muesste eigentlich eine dc hin.
633 if(printlist().size()) {
634 head(0,0," ");
636 bool converged = false;
637 try{
638 converged = solve_with_homotopy(itl,_trace);
639 }catch( Exception e) {
640 ::error(bDANGER, "hot failed\n");
641 throw e;
644 if(!converged){ itested();
645 _error = 1;
646 }else{
648 ::status.accept.start();
649 _sim->set_limit();
650 trace0("SOCK::veraop, accepting");
651 CARD_LIST::card_list.tr_accept();
652 ::status.accept.stop();
654 _sim->keep_voltages();
656 //========================
658 // Die Variablenwerte stehen schon durch solve_system in var_werte
659 // in dc_sysA und muessen noch nach A kopiert werden:
661 //A->var_werte = x_neu;
662 //free(dc_loesungA);
664 // A->var_werte = dc_loesungA;
665 // diff_werte, par_werte muessen auch gesetzt sein!
666 // in diesem Falle sind sie per default = 0
668 // solve somthing
670 // A->eval_lin_gl(dc_werteA,&matrixg,&matrixc,&vectorq);
672 trace1("matrix", 1);
674 /*--------------------------------------------------------------------------*/
675 void SOCK::verakons()
677 // n_eingaenge == #caps?
678 _sim->set_command_dc();
679 trace1("SOCK::kons", _caplist.size());
680 _sim->_time0 = 0; // just assert?
681 _sim->_dt0 = 0; // just assert?
682 advance_time();
683 _sim->_phase = p_INIT_DC;
684 total = n_eingaenge + n_vars + 1;
686 for (unsigned i=0; i < n_inputs(); i++) {
687 double d;
688 stream >> d;
689 trace3("SOCK::verakons setting input", _input_devs[i]->long_label(), i, d);
690 _input_devs[i]->set_value(d);
693 assert(_sim->_v0);
694 for (unsigned i=1; i <= n_vars; i++) {
695 stream >> _sim->_v0[i];
696 // trace2("SOCK::kons start ", i, _sim->_v0[i] );
698 if (printlist().size()) {
699 outdata(0.);
701 _sim->keep_voltages(); // v0->vdc
703 _error = 0; /* verakons(Dwork, x_new, q_dot, G, C); */
704 // n_vars = A->n_var;
706 for( unsigned i = 0; i < _caplist.size(); i++) {
707 trace1("SOCK::kons",_caplist[i]->long_label());
708 _caplist[i]->keep_ic(); // latch voltage applied to _v0
709 _caplist[i]->set_constant(true); // maybe not a good idea at all.
710 _caplist[i]->q_eval(); // so it will be updated
713 //================do_dc========
714 _sim->_uic = true;
715 _sim->_bypass_ok = false;
716 _sim->set_inc_mode_bad();
718 OPT::ITL itl = OPT::DCBIAS;
720 if(printlist().size()) {
721 head(0,0," ");
723 CARD_LIST::card_list.tr_begin();
724 bool converged = false;
725 try{
726 for( unsigned i = 0; i < _caplist.size(); i++) {
727 trace1("SOCK::kons",_caplist[i]->long_label());
728 // assert(!_caplist[i]->is_constant()); // NO caps are const, when they are in VS mode.
729 _caplist[i]->do_tr(); // so it will be updated. is this sufficient?
730 // is it sufficient to only queue caps?
732 converged = solve(itl,_trace);
733 // solve(OPT::TRHIGH,_trace);
734 // solve_with_homotopy(itl,_trace);
735 // homotopy is to much effort calling
736 // procedures must catch problems with convergence.
737 }catch( Exception e) {
738 ::error(bDANGER, "hot failed\n");
739 throw e;
741 if (!converged) {
742 ::error(bWARNING, "s_sock::verakons: solve did not converge\n");
743 converged = solve_with_homotopy(itl,_trace);
744 if (!converged) {
745 ::error(bWARNING, "s_sock::verakons: solve did not converge even with homotopy\n");
746 _error = 1;
749 ::status.accept.start();
750 assert(_sim->_uic);
751 CARD_LIST::card_list.tr_accept();
752 ::status.accept.stop();
754 // assert(_sim->_mode==s_SOCK);
755 if (printlist().size()) {
756 outdata(_sim->_time0);
758 _sim->_mode = s_SOCK; // for now.
760 _sim->keep_voltages();
761 _sim->zero_currents();
762 _sim->set_inc_mode_no();
764 // vera wants just cap stamps
765 for (unsigned i = 0; i < _caplist.size(); i++) { itested();
766 CARD* c = prechecked_cast<CARD*>(_caplist[i]);
767 assert(c);
768 trace1("verakons, loading cap", c->long_label());
769 _sim->_damp = 1.; // need raw stamps
770 c->tr_load();
773 for( unsigned i = 0; i < _caplist.size(); i++) {
774 /// oops. maybe the next command is tran?!
775 // (this is a hack!!)
776 _caplist[i]->set_constant(false);
779 /*--------------------------------------------------------------------------*/
780 #undef rescale
781 #define normalize
782 void SOCK::ev_iter()
784 trace1("SOCK::ev_iter", n_vars);
785 static double* aug;
786 double lambda;
787 if(!aug){ untested(); // quick hack!
788 assert(_sim->_aa.size()==n_vars);
789 aug = new double[n_vars*2+1];
791 #ifdef DO_TRACE
792 for (unsigned i=0; i < 1+2*n_vars; i++){ aug[i]=i; }
793 #endif
794 _sim->_aa = -(_sim->_acx.real());
795 assert(_sim->_aa.size()==n_vars);
796 double tmp[n_vars+1];
797 double xiin[n_vars+1];
798 double norm = 0;
799 for (unsigned i=0; i < n_vars; i++) {
800 stream >> tmp[i];
801 trace1("SOCK::ev_iter got", tmp[i]);
802 norm+=tmp[i]*tmp[i];
804 #ifdef normalize
805 norm=1./sqrt(norm);
806 #endif
807 for (unsigned i=0; i < n_vars; i++) {
808 #ifdef normalize
809 tmp[i]*=norm;
810 #endif
811 aug[n_vars*2-i] = tmp[i];
812 xiin[i]=tmp[i];
814 #ifdef normalize
815 aug[n_vars] = 0;
816 #else
817 aug[n_vars] = norm-1;
818 #endif
819 trace1("SOCK filled xi aa", _sim->_aa);
820 untested();
821 const BSMATRIX<double> C = _sim->_acx.imag();
822 C.rmul(aug-1,xiin-1);
823 stream >> lambda;
825 #ifdef rescale
826 for (unsigned i=0; i < n_vars; i++) {aug[i]*=lambda;}
827 #endif
829 _sim->_aa+= lambda * _sim->_acx.imag();
831 trace0("SOCK::ev_iter rmul");
832 _sim->_aa.rmul(tmp-1,xiin-1);
833 untested();
834 tmp[n_vars] = 0;
835 for (unsigned i=0; i <= n_vars; i++){ untested();
836 trace2("rhs",i,tmp[i]);
839 _sim->_aa.augment(aug);
840 assert(_sim->_aa.size()==n_vars+1);
841 trace1("SOCK augmented aa", _sim->_aa);
842 _sim->_aa.lu_decomp();
843 trace1("SOCK decomposed aa", _sim->_aa);
844 untested();
846 _sim->_aa.fbsub(tmp-1);
847 for (unsigned i=0; i <= n_vars; i++){
848 trace2("res",i,tmp[i]);
850 untested();
851 trace0("SOCK::ev_iter done");
852 _sim->_aa.deaugment();
853 assert(_sim->_aa.size()==n_vars);
854 stream << ((uint16_t)_error); stream.pad(6);
855 double resnormsq = 0;
856 for (unsigned i=0; i < n_vars; i++) { untested();
857 resnormsq+=tmp[i]*tmp[i];
858 stream << xiin[i]-tmp[i];
860 #ifdef rescale
861 resnormsq+=lambda*tmp[n_vars]*lambda*tmp[n_vars];
862 stream << lambda*(1-tmp[n_vars]);
863 #else
864 resnormsq+=tmp[n_vars]*tmp[n_vars];
865 stream << lambda-tmp[n_vars];
866 #endif
867 stream << resnormsq;
868 stream << SocketStream::eol;
869 trace0("SOCK::ev_iter sent");
871 /*--------------------------------------------------------------------------*/
872 void SOCK::set_param()
873 { itested();
874 string tmp[2];
875 stream >> tmp[0];
876 stream >> tmp[1];
877 PARAM_LIST* pl = CARD_LIST::card_list.params();
878 string paramcommand = tmp[0]+"={"+tmp[1]+"}";
879 trace3("set_param", tmp[0], tmp[1], paramcommand);
880 CS cmd(CS::_STRING, paramcommand);
881 pl->parse(cmd);
882 CARD_LIST::card_list.precalc_first(); // BUG? params don't propagate into sckts otherwise
883 CARD_LIST::card_list.precalc_last();
885 /*--------------------------------------------------------------------------*/
886 enum{
887 sOK=0, // ok, returned time step indicates next prefered
888 sNOCONV=1, // no convergence for second or 3. newton iteration: hope
889 // for success with shorter time step
890 sTRUNC=2, // Truncation error (time step not accepted (to long!))
891 // restart with shorter returned time step
892 sFIRSTNOCONV=3, // no convergence for first newton iteration after cons
893 // time step has no meaning, but reduction of time step should
894 // help
895 sTROUBLE=99 // exception in solve.
897 /*--------------------------------------------------------------------------*/
898 // init=0 continue with ruse of all old data (do 1 step)
899 // 1 restore op and do ~5 steps (could be used directly after a not accepted
900 // time step)
901 // 2 do cons_op followed by do ~5 step (depending on Euler,Gear,
902 // Trapezoid, options)
904 // return:
905 // ret (see above)
906 // dt. positive timestep, use instead in next call.
909 unsigned SOCK::transtep(unsigned init, double dt)
911 unsigned ret = sOK;
912 _error = 0;
913 trace3("SOCK::transtep", n_vars, init, dt);
914 _sim->set_command_tran();
915 _sim->restore_voltages(); // _vt1[ii] = _v0[ii] = vdc[ii];
916 _sim->_uic = false;
917 _sim->_phase = p_RESTORE;
919 unsigned stepno=-1;
920 double reftime = _sim->_time0;
922 if (dt==0.) {
923 dt = OPT::dtmin;
924 }else{
927 assert(dt);
929 if (init==0) { itested(); // continue
930 stepno = 1;
931 ::error(bDEBUG, "transient step, at %f, dt %f\n", _sim->_time0, dt);
932 _sim->_dt0 = dt;
933 assert(_sim->_time0);
934 _sim->_time0 += _sim->_dt0;
935 // CARD_LIST::card_list.tr_restore();
936 } else if (init==1) { itested(); // restore
937 assert(_sim->_time0 > 0);
938 // CARD_LIST::card_list.tr_restore();
939 stepno = 1;
940 _sim->_dt0 = dt/stepno;
941 ::error(bDEBUG, "restore step, dt %e\n", dt);
942 _sim->_time0 += _sim->_dt0;
943 } else if (init==2) {
944 _sim->_time0 = reftime = 0;
945 verakons(); // do we need it ?
946 stepno = 5;
947 _sim->_dt0 = dt/stepno;
948 ::error(bDEBUG, "initial step, dt %e\n", dt);
949 _sim->_time0 += _sim->_dt0;
950 } else { unreachable();
954 trace2("SOCK::transtep ", _sim->_phase, _sim->_mode);
956 advance_time(); // sink _time0 into devices
957 _sim->set_command_tran();
959 if (printlist().size()) {
960 outdata(reftime);
963 _sim->_phase = p_TRAN;
965 //_sim->_bypass_ok = false;
966 assert(_sim->_dt0 == dt/stepno);
967 //_sim->_genout = gen();
969 assert(_sim->analysis_is_tran());
971 // this is too expensive here.
972 // CARD_LIST::card_list.do_tr();
974 bool tr_converged;
975 for (unsigned i = stepno; i>0; --i) {
976 tr_converged = false;
977 try {
978 for( unsigned i = 0; i < _caplist.size(); i++) { itested();
979 trace1("SOCK::kons",_caplist[i]->long_label());
980 assert(!_caplist[i]->is_constant());
981 _caplist[i]->q_eval(); // so it will be updated. is this sufficient?
982 // is it sufficient to only queue caps?
984 tr_converged = solve(OPT::TRHIGH, _trace);
985 }catch (Exception e) { incomplete();
986 ret = sTROUBLE;
988 if (!tr_converged) { itested();
989 ::error(bDEBUG, "s_sock::transtep did not converge\n");
990 if (i==stepno) { untested();
991 ret = sFIRSTNOCONV;
992 break;
993 } else { untested();
994 ret = sNOCONV;
995 break;
997 }else{
1000 if(stepno>1) {
1001 /// uuh ooh HACK.
1002 assert(ret!=sFIRSTNOCONV);
1003 ::status.accept.start(); // accounting
1004 _sim->set_limit();
1005 CARD_LIST::card_list.tr_accept(); // accept solution in all components
1006 ::status.accept.stop();
1008 if (printlist().size()) {
1009 outdata(_sim->_time0);
1011 if(i>1){
1012 _sim->_time0 += _sim->_dt0;
1016 TIME_PAIR time_by = CARD_LIST::card_list.tr_review();
1017 double time_by_error_estimate = time_by._error_estimate;
1018 assert(time_by_error_estimate>=0);
1020 // if(!tr_converged?) { ... } else
1021 if (time_by_error_estimate > _sim->_time0) {
1022 dt = time_by_error_estimate - _sim->_time0;
1023 ::status.accept.start();
1024 _sim->set_limit();
1025 CARD_LIST::card_list.tr_accept();
1026 ::status.accept.stop();
1027 _sim->keep_voltages(); // vdc = v0
1028 assert(dt>0);
1029 }else{ itested();
1030 double t1 = _sim->_time0 - _sim->_dt0;
1031 dt = time_by_error_estimate - t1;
1032 assert(dt);
1033 ::error(bTRACE,"sock step not accepted at %f, need %f\n", reftime, dt);
1034 ret = sTRUNC;
1035 assert (dt>0); // hopefully.
1036 assert (dt < _sim->_dt0); // hopefully.
1037 dt *= stepno; // stepno is valid for next step.
1038 _sim->_time0 = reftime;
1039 tr_reject();
1042 #ifndef NDEBUG
1043 for (unsigned i=1; i <= n_vars; i++) {
1044 if(isnan(_sim->_i[i])||isnan(_sim->_vdcstack.top()[i]) ) {
1045 _error = 1;
1046 assert(!tr_converged);
1049 #endif
1051 _dthack = dt;
1052 return ret; // FIXME: proper status.
1054 /*--------------------------------------------------------------------------*/
1055 void SOCK::tr_reject()
1057 ::status.accept.start();
1058 _sim->_acceptq.clear();
1059 ++tr_steps_rejected_;
1060 ::status.accept.stop();
1062 /*--------------------------------------------------------------------------*/
1063 void SOCK::verakons_reply()
1065 stream << ((uint16_t)_error); stream.pad(6);
1066 for (unsigned i=1; i <= n_vars; i++) {
1067 trace1("SOCK::kons_reply", _sim->vdc()[i]);
1068 stream << _sim->vdc()[i];
1072 // now i contains the negative sum of the cap value.
1073 // does this break anything?
1075 for (unsigned i=1; i <= n_vars; i++) /* Q-Punkt == I == RS */
1077 trace1("SOCK::verakons_reply dqdt", _sim->_i[i]);
1078 stream << _sim->_i[i];
1081 if(_dump_matrix){
1082 _out << "u,dq=i: \n";
1083 for (unsigned i=0; i <= n_vars; i++) /* Variablen-Werte */
1085 _out << _sim->vdc()[i] << "," << _sim->_i[i] << "\n" ;
1089 trace0("SOCK::verakons_reply ac_snap");
1090 ac_snapshot(); // FIXME: to verakons()
1092 send_matrix();
1094 assert(stream.bufsize() >= total);
1095 stream << SocketStream::eol;
1097 // for( unsigned i = 0; i < _caplist.size(); i++)
1098 // {
1099 // trace1("unlatching", i);
1101 // dashier umgekehrt.
1102 // commonstash[i] = _caplist[i]->common();
1103 // detach(_caplist[i]);
1105 // COMMON_COMPONENT* c = bm_dispatcher.clone("eval_bm_value");
1106 // COMMON_COMPONENT* dc = c->deflate();
1108 // _caplist[i]->attach_common(dc);
1110 // _caplist[i]->keep_ic(); // latch voltage applied to _v0
1113 // }
1117 void SOCK::transtep_reply(unsigned ret, bool eol)
1119 _error = 0;
1120 stream << _error; stream.pad(6);
1121 stream << (uint64_t)ret;
1122 stream << _dthack;
1124 for (unsigned i=1; i <= n_vars; i++) {
1125 trace2("SOCK::transtep_reply v ", _sim->_vdcstack.top()[i],i);
1126 stream << _sim->_vdcstack.top()[i];
1129 // OUCH, move to main loop.
1130 if(eol) {
1131 stream << SocketStream::eol;
1135 void SOCK::transtep_gc_reply(unsigned ret)
1136 { itested();
1137 transtep_reply(ret, false);
1139 for (unsigned i=1; i <= n_vars; i++)
1141 trace1("SOCK::transtep_gc_reply dqdt", _sim->_i[i]);
1142 stream << _sim->_i[i];
1145 trace0("SOCK::transtep_gc_reply ac_snap");
1146 ac_snapshot(); // BUG: calls tr_begin
1147 send_matrix();
1148 assert(stream.bufsize() >= total);
1149 stream << SocketStream::eol;
1151 /*--------------------------------------------------------------------------*/
1152 void SOCK::verainit_reply()
1154 trace4("SOCK::verainit_reply ", _error, n_vars, length, var_namen_total_size);
1155 stream << _error; stream.pad(6);
1156 stream << int32_t (n_vars); stream.pad(4);
1157 stream << int32_t (var_namen_total_size); stream.pad(4);
1159 assert(stream.tcur() == 24);
1161 for (unsigned i = 0; i < n_vars; i++) {
1162 trace2("SOCK::verainit_reply", i, var_namen_arr[i]);
1163 putstring8( &stream, var_namen_arr[i]);
1164 stream << '\t'; stream.pad(7);
1167 //good idea?? not yet. vera insists on branch node
1169 // for (unsigned i=0; i < n_inputs; i++)
1170 // {
1171 // trace1("putting name " + input_names[i], i);
1172 // putstring8( &stream, input_names[i]);
1173 // stream << '\t'; stream.pad(7);
1174 // }
1175 stream.flush();
1177 trace0("done verainit_reply");
1179 /*--------------------------------------------------------------------------*/
1180 void SOCK::veraop_reply()
1182 assert(n_vars==_sim->_total_nodes);
1183 trace1("SOCK::veraop_reply ", n_vars);
1184 stream << _error; stream.pad(6);
1185 for (unsigned i=1; i <= n_vars; i++) /* Variablen-Werte */
1187 stream << _sim->vdc()[i];
1189 if(_dump_matrix){
1190 _out << "i,u: \n";
1191 for (unsigned i=0; i <= n_vars; i++) /* Variablen-Werte */
1193 _out << _sim->_i[i] << "," << _sim->vdc()[i] << "\n" ;
1197 trace0("SOCK::veraop_reply taking ac snapshot (matrix only?).");
1198 ac_snapshot();
1199 send_matrix();
1200 stream << SocketStream::eol;
1202 trace0("SOCK::veraop_reply sent");
1204 total = 2*n_vars_square+n_vars+1;
1205 assert(stream.bufsize() >= total);
1206 if (printlevel >= 1)
1208 userinfo(1,"vera_titan_ak","Sende: Error %i Framenumber %i, Laenge %i\n",
1209 _error,frame_number,total);
1212 /*--------------------------------------------------------------------------*/
1213 /*--------------------------------------------------------------------------*/
1214 void SOCK::send_matrix()
1216 const BSMATRIX<double> G = _sim->_acx.real();
1217 const BSMATRIX<double> C = _sim->_acx.imag();
1218 if(_dump_matrix){
1219 _out << "G\n" << G << "\n";
1220 _out << "C\n" << C << "\n";
1222 trace0("SOCK::send_matrix G");
1223 for (unsigned i=1; i <= n_vars; i++){
1224 for (unsigned j=1; j <= n_vars; j++) {
1225 stream << G.s(j,i);
1228 trace0("SOCK::send_matrix C");
1229 for (unsigned i=1; i <= n_vars; i++){
1230 for (unsigned j=1; j <= n_vars; j++) {
1231 stream << C.s(j,i);
1235 /*--------------------------------------------------------------------------*/
1236 void SOCK::cap_prepare(void)
1238 trace1("SOCK::cap_prepare", _caplist.size() );
1239 assert(!_capstash);
1240 _capstash = new CARDSTASH[_caplist.size()];
1242 for (unsigned ii = 0; ii < _caplist.size(); ++ii) {
1243 _caplist[ii]->inc_probes(); // we need to keep track of it
1244 _capstash[ii] = _caplist[ii]; // stash the std value
1246 if(_caplist[ii]->has_common()){
1247 trace1("SOCK::cap_prepare. have common", _caplist[ii]->value());
1248 // _caplist[ii]->set_value(_caplist[ii]->value(), 0); // zap out extensions
1249 // _caplist[ii]->set_constant(false); // update HACK?
1251 // all devices need individual commons.
1252 _caplist[ii]->attach_common(_caplist[ii]->common()->clone());
1253 assert(_caplist[ii]->has_common());
1254 }else{
1255 // _sweepval[ii] = _zap[ii]->set__value(); // point to value to patch
1256 COMMON_COMPONENT* c = bm_dispatcher.clone("eval_bm_value");
1257 double capval = _caplist[ii]->value();
1258 trace2("SOCK::cap_prepare, attaching common", _caplist[ii]->long_label(), capval);
1259 c->set_value(capval);
1260 COMMON_COMPONENT* dc = c->deflate();
1261 assert(dc);
1263 _caplist[ii]->set_value(_caplist[ii]->value(), dc); // zap out extensions
1264 _caplist[ii]->set_constant(false); // so it will be updated
1265 trace1("SOCK::cap_prepare calling precalc_first", _caplist[ii]->long_label());
1266 _caplist[ii]->precalc_first();
1267 trace0("SOCK::cap_prepare calling precalc_last");
1268 _caplist[ii]->precalc_last();
1269 trace0("SOCK::cap_prepare calling trbegin");
1270 _caplist[ii]->tr_begin();
1274 /*--------------------------------------------------------------------------*/
1275 void SOCK::cap_reset(void)
1277 trace0("SOCK::cap_reset");
1278 for (unsigned ii = 0; ii < _caplist.size(); ++ii) {
1279 _capstash[ii].restore();
1280 _caplist[ii]->dec_probes();
1281 // _caplist[ii]->precalc_first();
1282 // _caplist[ii]->precalc_last();
1284 delete[] _capstash;
1285 _capstash = NULL;
1286 trace0("SOCK::cap_reset done");
1288 /*--------------------------------------------------------------------------*/
1289 SOCK::~SOCK()
1291 trace0("SOCK::~SOCK()");
1293 /*--------------------------------------------------------------------------*/
1294 // vim:ts=8:sw=2:noet: