Xyce  6.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
N_DEV_Region.C
Go to the documentation of this file.
1 //-----------------------------------------------------------------------------
2 // Copyright Notice
3 //
4 // Copyright 2002 Sandia Corporation. Under the terms
5 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S.
6 // Government retains certain rights in this software.
7 //
8 // Xyce(TM) Parallel Electrical Simulator
9 // Copyright (C) 2002-2014 Sandia Corporation
10 //
11 // This program is free software: you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation, either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 //-------------------------------------------------------------------------
24 
25 //-------------------------------------------------------------------------
26 // Filename : $RCSfile: N_DEV_Region.C,v $
27 //
28 // Purpose :
29 //
30 // Special Notes :
31 //
32 // Creator : Eric R. Keiter, SNL
33 //
34 // Creation Date : 07/19/06
35 //
36 // Revision Information:
37 // ---------------------
38 //
39 // Revision Number: $Revision: 1.17 $
40 //
41 // Revision Date : $Date: 2014/02/24 23:49:15 $
42 //
43 // Current Owner : $Author: tvrusso $
44 //-------------------------------------------------------------------------
45 
46 #include <Xyce_config.h>
47 
48 
49 // ---------- Standard Includes ----------
50 
51 #include <N_UTL_Misc.h>
52 #include <N_UTL_Xyce.h>
53 
54 #ifdef Xyce_DEBUG_DEVICE
55 #include <iostream>
56 #endif
57 
58 #ifdef HAVE_CMATH
59 #include <cmath>
60 #else
61 #include <math.h>
62 #endif
63 
64 #ifdef Xyce_DEBUG_DEVICE
65 #ifdef HAVE_CSTDIO
66 #include <cstdio>
67 #else
68 #include <stdio.h>
69 #endif
70 #endif
71 
72 
73 // ---------- Xyce Includes ----------
74 #include <N_DEV_Const.h>
75 #include <N_DEV_ExternData.h>
76 #include <N_DEV_SolverState.h>
77 #include <N_DEV_DeviceOptions.h>
78 #include <N_DEV_MatrixLoadData.h>
79 #include <N_DEV_DeviceInstance.h>
80 #include <N_DEV_RegionData.h>
81 
82 #include <N_LAS_Matrix.h>
83 #include <N_LAS_MultiVector.h>
84 #include <N_LAS_Vector.h>
85 
86 #include <N_DEV_Region.h>
87 #include <N_DEV_Specie.h>
88 #include <N_DEV_ScalingVars.h>
89 #include <N_UTL_Expression.h>
90 
91 namespace Xyce {
92 namespace Device {
93 
94 //-----------------------------------------------------------------------------
95 // Function : Region::Region
96 // Purpose : constructor 1
97 // Special Notes : creates reaction region with default reaction network
98 // Scope : public
99 // Creator :
100 // Creation Date : 8/24/06
101 //-----------------------------------------------------------------------------
103  const DeviceOptions & devOp,
104  const SolverState & solst,
105  bool sourceOn)
106  : name(rd.name),
107  outputName(rd.outName),
108  devOptions(devOp),
109  solState(solst),
110  regData(rd),
111  useScaledVariablesFlag(false),
112  variablesScaledFlag(false),
113  rateConstantsScaledFlag(false),
114  callsOTEC(0),
115  baseReactionIndex(-1),
116  x0(0.0),
117  a0(0.0),
118  C0(0.0),
119  D0(0.0),
120  u0(0.0),
121  R0(0.0),
122  rR0(0.0),
123  t0(0.0),
124  k0(0.0),
125  rt0(0.0),
126  rk0(0.0),
127  outputBefore1(false),
128  outputBefore2(false)
129 {
130  theReactions.setApplySources(sourceOn);
132 }
133 
134 //-----------------------------------------------------------------------------
135 // Function : Region::Region
136 // Purpose : constructor 2
137 // Special Notes : creates reaction region with copied reaction network
138 // for now does nothing but call initializers, but moved
139 // out of header file in case we want it to be more than a
140 // simple inlined deal.
141 // Scope : public
142 // Creator :
143 // Creation Date : 7/29/06
144 //-----------------------------------------------------------------------------
146  const DeviceOptions & devOp,
147  const SolverState & solst,
148  ReactionNetwork & reactionNet)
149 
150  : name(rd.name),
151  outputName(rd.outName),
152  devOptions(devOp),
153  solState(solst),
154  regData(rd),
155  useScaledVariablesFlag(false),
156  variablesScaledFlag(false),
157  rateConstantsScaledFlag(false),
158  callsOTEC(0),
159  baseReactionIndex(-1),
160  x0(0.0),
161  a0(0.0),
162  C0(0.0),
163  D0(0.0),
164  u0(0.0),
165  R0(0.0),
166  rR0(0.0),
167  t0(0.0),
168  k0(0.0),
169  rt0(0.0),
170  rk0(0.0),
171  outputBefore1(false),
172  outputBefore2(false),
173  theReactions(reactionNet)
174 {
175 #ifdef Xyce_DEBUG_DEVICE
176  if (devOptions.debugLevel > 0)
177  {
178  Xyce::dout() << theReactions << std::endl;
179  }
180 #endif
181 }
182 
183 //-----------------------------------------------------------------------------
184 // Function : Region::~Region
185 // Purpose : destructor
186 // Special Notes :
187 // Scope : public
188 // Creator :
189 // Creation Date : 7/29/06
190 //-----------------------------------------------------------------------------
192 {
194 }
195 
196 //-----------------------------------------------------------------------------
197 // Function : Region::createDefaultRectionNetwork
198 // Purpose : like it says
199 // Special Notes :
200 // Scope : private
201 // Creator :
202 // Creation Date : 7/29/06
203 //-----------------------------------------------------------------------------
204 void
205 Region::createDefaultReactionNetwork(const std::string &reactionSpecFile)
206 {
208 
209  theReactions.setReactionNetworkFromFile(reactionSpecFile);
210 
211 #ifdef Xyce_DEBUG_DEVICE
212  if (devOptions.debugLevel > 0)
213  {
214  Xyce::dout() << theReactions << std::endl;
215  }
216 #endif
217 
218 }
219 
220 //-----------------------------------------------------------------------------
221 // Function : Region::initializeReactionNetwork
222 // Purpose : Initialize the 0-d reaction network equations
223 // Special Notes : The reaction network itself has already been created when
224 // the region was set up, here we just initialize some
225 // properties of it.
226 // Scope : public
227 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
228 // Creation Date : 3/29/06
229 //-----------------------------------------------------------------------------
231 {
232 
233  int cSize=theReactions.getNumConstants();
234  int sSize=theReactions.getNumSpecies();
235 
236  setupScalingVars(sv);
237 
239 
240  // We will need to get the initial conditions in some other way, too.
241  // this presumes we have all these specific named species. We might have
242  // more, or fewer.
243  if (cSize > 0)
244  {
245  theConstantConcentrations.resize(cSize,0.0);
246  }
247 
248  // initial condition
249  // These are just this way for testing purposes.
250  if (sSize > 0)
251  {
252  initialConcentrations.resize(sSize,0.0);
253  }
254 
255  // Estimate the electron and hole concentrations based on the
256  // doping levels. For now we are just considering the exact center
257  // of the depletion region.
258 
259  if (sSize > 0 ) // don't initialize any concentrations at all if there
260  // are no variable species!
261  {
262  int icSize = theReactions.getNumInitialConditions();
263  int i;
264  for (i=0; i<icSize; ++i)
265  {
266  std::pair<std::string,double> theIC=theReactions.getInitialCondition(i);
267  int specIndex=theReactions.getReactantNum(theIC.first);
268  if (specIndex < 0)
269  theConstantConcentrations[-(specIndex+1)] = theIC.second;
270  else
271  initialConcentrations[specIndex] = theIC.second;
272  }
273  }
274 
275 }
276 
277 //-----------------------------------------------------------------------------
278 // Function : Region::setInitialCondition
279 // Purpose :
280 // Special Notes :
281 // Scope : public
282 // Creator :
283 // Creation Date : 3/29/06
284 //-----------------------------------------------------------------------------
285 void Region::setInitialCondition(const std::string & reactantname, const double val)
286 {
287  int specIndex=theReactions.getReactantNum(reactantname);
288  initialConcentrations[specIndex] = val;
289 }
290 
291 //-----------------------------------------------------------------------------
292 // Function : Region::addSource
293 // Purpose : add a source term to the reaction network
294 // Special Notes :
295 // Scope : public
296 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
297 // Creation Date : 8/4/06
298 //-----------------------------------------------------------------------------
299 void Region::addSource(std::string speciesName, Util::Expression *expr)
300 {
301  theReactions.addSourceTerm(speciesName, expr);
302 }
303 
304 //-----------------------------------------------------------------------------
305 // Function : Region::addMasterSource
306 // Purpose : add a master source term to the reaction network
307 // Special Notes : "master" source terms are those that depend on a single
308 // master source value that is set each time we evaluate
309 // the RHS.
310 // Scope : public
311 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
312 // Creation Date : 8/4/06
313 //-----------------------------------------------------------------------------
314 void Region::addMasterSource(std::string speciesName)
315 {
316  theReactions.addMasterSourceTerm(speciesName);
317 }
318 
319 //-----------------------------------------------------------------------------
320 // Function : Region::setRateConstants
321 // Purpose : Set rate constants for reactions defined in
322 // initializeReactionNetwork. This is meant to be called
323 // from updateTemperature.
324 // Special Notes : Cheesy hard-coded version for initial testing
325 // Scope : public
326 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
327 // Creation Date : 3/29/06
328 //-----------------------------------------------------------------------------
330 {
332 
333 #ifdef Xyce_DEBUG_DEVICE
334 
335  if (!outputBefore1)
336  {
337  if (devOptions.debugLevel > 0)
338  Xyce::dout() << theReactions << std::endl;
339  outputBefore1 = true;
340  }
341 
342 #endif
343 
344  // if the variables have been scaled, then the rate constants should be
345  // as well:
347  {
349  }
350 
351 #ifdef Xyce_DEBUG_DEVICE
353  {
354  if (devOptions.debugLevel > 0)
355  {
356  Xyce::dout() << "Scaled Reactions: " << std::endl;
357  Xyce::dout() << theReactions << std::endl;
358  }
359  outputBefore2=true;
360  }
361 #endif
362 }
363 
364 //----------------------------------------------------------------------------
365 // Function : Region::setupScalingVars
366 // Purpose :
367 //
368 // Special Notes : Most of these aren't used. The important ones are
369 // T0 and C0.
370 //
371 // Scope : public
372 // Creator : Eric Keiter, SNL, Electrical and Microsystems Modeling
373 // Creation Date : 6/01/06
374 //----------------------------------------------------------------------------
376 {
377  t0 = sv.t0;
378  C0 = sv.C0;
379  x0 = sv.x0;
380  double rx0 = 1.0/x0;
381 
382  a0 = sv.a0;
383 
384  D0 = sv.D0;
385  R0 = sv.R0;
386 
387  rR0 = 1.0/R0;
388 
389  rk0 = C0*t0;
390  rt0 = 1.0/t0;
391  k0 = 1.0/rk0;
392 
393 #ifdef Xyce_DEBUG_DEVICE
394  if (devOptions.debugLevel > -2)
395  {
396  Xyce::dout() << "N_DEV_Region::setupScalingVars:" << std::endl;
397  Xyce::dout().width(20);
398  Xyce::dout().precision(12);
399  Xyce::dout() << " " << std::endl;
400  Xyce::dout() << "t0 = " << t0 << std::endl;
401  Xyce::dout() << "x0 = " << x0 << std::endl;
402  Xyce::dout() << "a0 = " << a0 << std::endl;
403  Xyce::dout() << "C0 = " << C0 << std::endl;
404  Xyce::dout() << "D0 = " << D0 << std::endl;
405  Xyce::dout() << "R0 = " << R0 << std::endl;
406  Xyce::dout() << "k0 = " << k0 << std::endl;
407  Xyce::dout() << "rk0 = " << rk0 << std::endl;
408  }
409 #endif
410 
411 }
412 
413 //----------------------------------------------------------------------------
414 // Function : Region::scaleVariables
415 // Purpose : Applies the scaling variables.
416 // Special Notes :
417 // Scope : public
418 // Creator : Eric Keiter, SNL, Electrical and Microsystems Modeling
419 // Creation Date : 6/01/06
420 //----------------------------------------------------------------------------
422 {
423  int i=0;
424  int size=0;
425 
426  // vector of constant concentrations (species held fixed)
427  size = theConstantConcentrations.size();
428  for (i=0;i<size;++i)
429  {
431  }
432 
433  // working storage for communicating between updateIntermediateVars
434  // and updatePrimaryState
435  size = tempConcentrations.size();
436  for (i=0;i<size;++i)
437  {
438  tempConcentrations[i] /= C0;
439  }
440 
441  // initial conditions
442  size = initialConcentrations.size();
443  for (i=0;i<size;++i)
444  {
446  }
447 
448  variablesScaledFlag = true;
449 }
450 
451 //----------------------------------------------------------------------------
452 // Function : Region::unscaleVariables
453 // Purpose : Restores things to normal units.
454 // Special Notes :
455 // Scope : public
456 // Creator : Eric Keiter, SNL, Electrical and Microsystems Modeling
457 // Creation Date : 6/01/06
458 //----------------------------------------------------------------------------
460 {
461  int i=0;
462  int size=0;
463 
464  // vector of constant concentrations (species held fixed)
465  size = theConstantConcentrations.size();
466  for (i=0;i<size;++i)
467  {
469  }
470 
471  // working storage for communicating between updateIntermediateVars
472  // and updatePrimaryState
473  size = tempConcentrations.size();
474  for (i=0;i<size;++i)
475  {
476  tempConcentrations[i] *= C0;
477  }
478 
479  // initial conditions
480  size = initialConcentrations.size();
481  for (i=0;i<size;++i)
482  {
484  }
485 
486  variablesScaledFlag = false;
487 }
488 
489 //----------------------------------------------------------------------------
490 // Function : Region::scaleRateConstants
491 // Purpose :
492 // Special Notes : This function assumes that the rate constants are
493 // in units of cm^3/s, need to be multiplied by C0*t0.
494 //
495 // Some rate constants include e- or h+ densities in them.
496 // ie, are k*Ne or k*Nh, rather than just k. For these
497 // rate constants, the scalar multiple should just be t0.
498 //
499 // To understand this consider the expression:
500 //
501 // k * Na * Nb, where k is a rate and Na and Nb are
502 // the concentrations of reactants. If the variables have
503 // been scaled already, then Na and Nb are already scaled
504 // to dimensionless units. (ie Na /= C0).
505 //
506 // k, being in cm^3/s, needs to be multiplied by t0/C0. So,
507 // the total scaling multiplied by the expression is:
508 //
509 // (rate scaling) * (concentration scaling)^2
510 // (t0*C0) * 1/C0 * 1/C0 = t0/C0.
511 //
512 // This is (correctly) the same as the scaling applied
513 // to dNa/dt, which will also be multiplied by t0/C0.
514 //
515 // In the case of an implicit e- density, then k is actually
516 // k*Ne, in units of s^-1. Then the expression is:
517 //
518 // kNe * Nb. The scalar will be:
519 //
520 // t0 * 1/C0 = t0/C0, which is correct.
521 //
522 // So the punchline is:
523 //
524 // (1) rates including Ne or Nh, multiply by t0.
525 // (2) rates not including Ne or Nh, multiply by rk0=C0*t0.
526 //
527 // For now, just like the other reaction-specific functions, this function
528 // is hardwired to a specific reaction network. It will have to be
529 // generalized later.
530 //
531 // Scope : public
532 // Creator : Eric Keiter, SNL, Electrical and Microsystems Modeling
533 // Creation Date : 6/01/06
534 //----------------------------------------------------------------------------
536 {
538 
540 }
541 
542 //----------------------------------------------------------------------------
543 // Function : Region::unscaleRateConstants
544 // Purpose :
545 // Special Notes :
546 // Scope : public
547 // Creator :
548 // Creation Date : 6/01/06
549 //----------------------------------------------------------------------------
551 {
553 
554  rateConstantsScaledFlag = false;
555 }
556 
557 //-----------------------------------------------------------------------------
558 // Function : Region::outputTecplot
559 // Purpose :
560 // Special Notes :
561 // Scope : public
562 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
563 // Creation Date : 7/19/06
564 //-----------------------------------------------------------------------------
566 {
567  bool bsuccess = true;
568 
569  int i;
570  char filename[32]; for(i=0;i<32;++i) filename[i] = static_cast<char>(0);
571 
572  sprintf(filename,"%s.dat",outputName.c_str());
573 
574  double time = solState.currTime;
575  double step = solState.currTimeStep;
576 
577 #ifdef Xyce_DEBUG_DEVICE
579  {
580  Xyce::dout() << std::endl;
581  Xyce::dout() << section_divider << std::endl;
582  Xyce::dout() << "In N_DEV_DiodePDEInstance::outputTecplot. filename = ";
583  Xyce::dout() << std::string(filename);
584  Xyce::dout() << " time = " << time;
585  Xyce::dout() << " step = " << step;
586  Xyce::dout() << std::endl;
587  }
588 #endif
589 
590  FILE *fp1;
591 
592  if (callsOTEC <= 0)
593  {
594  fp1 = fopen(filename,"w");
595  }
596  else
597  {
598  fp1 = fopen(filename,"a");
599  }
600 
601  // If this is the first call, print the header.
602  int rSize=theReactions.getNumSpecies();
603  int cSize=theReactions.getNumConstants();
604  if (callsOTEC <= 0)
605  {
606  fprintf(fp1,
607  " TITLE = \"Data for reaction model: %s.\",\n", name.c_str());
608  fprintf(fp1,"%s","\tVARIABLES = \"TIME \",\n");
609 
610  for (i=0;i<cSize;++i)
611  {
612  fprintf(fp1, "\t \"%s \",\n" , (theReactions.getConstantsName(i)).c_str());
613  }
614 
615  for (i=0;i<rSize;++i)
616  {
617  fprintf(fp1,"\t \"%s \",\n", (theReactions.getSpeciesName(i)).c_str());
618  }
619  fprintf(fp1,"%s","\tZONE F=POINT\n");
620  }
621 
622  // Now print the data:
623  fprintf(fp1," %20.12e", solState.currTime);
624 
625 
626  for (i=0;i<cSize;++i)
627  {
628  double printVal =
630  fprintf(fp1," %20.12e", printVal);
631  }
632 
633  for (i=0;i<rSize;++i)
634  {
635  double printVal =
637  fprintf(fp1," %20.12e", printVal);
638  }
639 
640  fprintf(fp1,"%s","\n");
641 
642  ++callsOTEC;
643  fclose(fp1);
644 
645  return bsuccess;
646 }
647 
648 //-----------------------------------------------------------------------------
649 // Function : Region::setupJacStamp
650 //
651 // Purpose : adds reaction region's information to jac stamp.
652 //
653 // Special Notes : Modified to return the base index.
654 //
655 // Scope : public
656 // Creator : Eric R. Keiter
657 // Creation Date : 7/19/06
658 //-----------------------------------------------------------------------------
659 void Region::setupJacStamp ( std::vector< std::vector<int> > & jacStamp,
660  std::vector<int> &colDep,
661  int & firstReactant,
662  int & lastIndex )
663 {
664  int concentrationSize = theReactions.getNumSpecies();
665 
666  if (concentrationSize != 0 && !(regData.doNothing) ) // then we have jacStamp modifications to do
667  {
668  if (colDep.size() != 2)
669  {
670  Report::DevelFatal0() << "Region::setupJacStamp ERROR: colDep != 2 ";
671  }
672 
673  int stampSize=jacStamp.size();
674  baseReactionIndex=stampSize;
675  jacStamp.resize(stampSize+concentrationSize);
676 
677  // This simply sets a full square block, irresepective of how the
678  // network actually couples variables. First cut, possibly inefficient,
679  // probably not worth doing more specifically unless there's a huge
680  // reaction network with many species and very sparse matrix.
681  for (int i=0; i<concentrationSize; ++i)
682  {
683 #if 0
684  jacStamp[baseReactionIndex+i].resize(concentrationSize+2);
685 #else
686  jacStamp[baseReactionIndex+i].resize(concentrationSize);
687 #endif
688  for (int j=0;j<concentrationSize; ++j)
689  {
690  jacStamp[baseReactionIndex+i][j]=baseReactionIndex+j;
691  }
692 
693 #if 0
694  // This is why colDep must be of size 2. (one for e-, one for h+)
695  // add the colDep colummns:
696  jacStamp[baseReactionIndex+i][concentrationSize ]=colDep[0];
697  jacStamp[baseReactionIndex+i][concentrationSize+1]=colDep[1];
698 #endif
699  }
700  }
701  firstReactant = baseReactionIndex;
702  lastIndex = jacStamp.size()-1;
703 }
704 
705 //-----------------------------------------------------------------------------
706 // Function : Region::registerLIDs
707 // Purpose :
708 // Special Notes : updates the intIndex
709 // Scope : public
710 // Creator : Eric R. Keiter
711 // Creation Date : 7/19/06
712 //-----------------------------------------------------------------------------
713 void Region::registerLIDs( const std::vector<int> & intLIDVec,
714  const std::vector<int> & extLIDVec,
715  int & intIndex)
716 {
717 
718  if ( !(regData.doNothing) )
719  {
720  if (baseReactionIndex != -1)
721  {
722  int rSize = theReactions.getNumSpecies();
723  li_Concentrations.clear();
724  li_Concentrations.resize(rSize);
725 #ifdef Xyce_DEBUG_DEVICE
726  if (devOptions.debugLevel > 0)
727  {
728  Xyce::dout() << " li_Concentrations: " << std::endl;
729  }
730 #endif
731  for (int i=0;i<rSize;++i)
732  {
733  li_Concentrations[i] = intLIDVec[intIndex++];
734 
735 #ifdef Xyce_DEBUG_DEVICE
736  if (devOptions.debugLevel > 0)
737  {
738  Xyce::dout() << " li_Concentrations["<< i << "] = " << li_Concentrations[i] << std::endl;
739  }
740 #endif
741  }
742  }
743  }
744 }
745 
746 //-----------------------------------------------------------------------------
747 // Function : Region::augmentNameMap
748 // Purpose :
749 // Special Notes :
750 // Scope : public
751 // Creator : Eric R. Keiter
752 // Creation Date : 7/20/06
753 //-----------------------------------------------------------------------------
755  std::map<int,std::string> & intNameMap,
756  DeviceInstance & di)
757 {
758 
759  std::string tmpstr;
760 
761  if ( !(regData.doNothing) )
762  {
763  if (baseReactionIndex != -1)
764  {
765  int rSize=theReactions.getNumSpecies();
766  for (int i=0;i<rSize;++i)
767  {
768  std::string speciesName=theReactions.getSpeciesName(i);
769  tmpstr = name+"_Conc_"+speciesName;
770  di.spiceInternalName(tmpstr);
771  intNameMap[li_Concentrations[i]] = tmpstr;
772  }
773  }
774  }
775 }
776 
777 //-----------------------------------------------------------------------------
778 // Function : Region::registerStateLIDs
779 // Purpose :
780 // Special Notes :
781 // Scope : public
782 // Creator : Eric R. Keiter
783 // Creation Date : 7/20/06
784 //-----------------------------------------------------------------------------
786  (const std::vector<int> & staLIDVec, int & i)
787 {
788  if (baseReactionIndex != -1)
789  {
790  int rSize = theReactions.getNumSpecies();
791  li_state_Concentrations.resize(rSize);
792  for (int j=0;j<rSize;++j)
793  {
794  li_state_Concentrations[j]=staLIDVec[i++];
795  }
796  }
797 }
798 
799 //-----------------------------------------------------------------------------
800 // Function : Region::registerJacLIDs
801 // Purpose :
802 // Special Notes :
803 // Scope : public
804 // Creator : Eric R. Keiter
805 // Creation Date : 7/20/06
806 //-----------------------------------------------------------------------------
808  ( const std::vector< std::vector<int> > & jacLIDVec,
809  const std::vector<int> &map,
810  const std::vector< std::vector<int> > &map2
811  )
812 {
813  if ( !(regData.doNothing) )
814  {
815  if (baseReactionIndex != -1)
816  {
817  int rSize = theReactions.getNumSpecies();
818  AConcentrationEquConcentrationNodeOffsets.clear();
819  AConcentrationEquAuxNodeOffsets.clear();
820 
821  AConcentrationEquConcentrationNodeOffsets.resize(rSize);
822  AConcentrationEquAuxNodeOffsets.resize(rSize);
823 
824  for (int i=0;i<rSize;++i)
825  {
826  AConcentrationEquConcentrationNodeOffsets[i].resize(rSize);
827  for (int j=0;j<rSize;++j)
828  {
829  AConcentrationEquConcentrationNodeOffsets[i][j]=
830  jacLIDVec[map[baseReactionIndex+i]][map2[baseReactionIndex+i][j]];
831  }
832 
833 #if 0
834  int bRI = baseReactionIndex;
835  AConcentrationEquAuxNodeOffsets[i].resize(2);
836  for (int j=0; j<2; ++j)
837  {
838  AConcentrationEquAuxNodeOffsets[i][j]=
839  jacLIDVec[map[bRI+i]][map2[bRI+i][rSize+j]];
840  }
841 #endif
842  }
843  }
844  }
845 
846 }
847 
848 //-----------------------------------------------------------------------------
849 // Function : Region::setupPointers()
850 // Purpose :
851 // Special Notes :
852 // Scope : public
853 // Creator : Eric R. Keiter, SNL
854 // Creation Date : 5/19/10
855 //-----------------------------------------------------------------------------
856 void Region::setupPointers (N_LAS_Matrix & dfdx, N_LAS_Matrix & dqdx)
857 {
858  if ( !(regData.doNothing) )
859  {
860  int rSize = theReactions.getNumSpecies();
861 
862  dfdxConcEquConcVarPtrs.clear();
863  dfdxConcEquConcVarPtrs.resize(rSize);
864 
865  dqdxConcEquConcVarPtrs.clear();
866  dqdxConcEquConcVarPtrs.resize(rSize);
867 
868 #if 0
869  dfdxConcEquAuxVarPtrs.clear();
870  dfdxConcEquAuxVarPtrs.resize(rSize);
871 
872  dqdxConcEquAuxVarPtrs.clear();
873  dqdxConcEquAuxVarPtrs.resize(rSize);
874 #endif
875 
876  for (int i=0;i<rSize;++i)
877  {
878  dfdxConcEquConcVarPtrs[i].resize(rSize,0);
879  dqdxConcEquConcVarPtrs[i].resize(rSize,0);
880 
881  for (int j=0;j<rSize; ++j)
882  {
883  int lidRow = li_Concentrations[i];
884  int lidCol = li_Concentrations[j];
885 
886  double * dfdxPtr = dfdx.returnRawEntryPointer (lidRow, lidCol);
887  dfdxConcEquConcVarPtrs[i][j] = dfdxPtr;
888 
889  double * dqdxPtr = dqdx.returnRawEntryPointer (lidRow, lidCol);
890  dqdxConcEquConcVarPtrs[i][j] = dqdxPtr;
891  }
892 
893 #if 0
894  dfdxConcEquAuxVarPtrs[i].resize(2,0);
895  dqdxConcEquAuxVarPtrs[i].resize(2,0);
896  for (int j=0;j<2; ++j)
897  {
898  int lidRow = li_Concentrations[i];
899  int coloffset = AConcentrationEquAuxNodeOffsets[i][j];
900 
901  dfdxConcEquAuxVarPtrs[i][j] = &(dfdx[lidRow][coloffset]);
902  dqdxConcEquAuxVarPtrs[i][j] = &(dqdx[lidRow][coloffset]);
903  }
904 #endif
905  }
906  }
907 }
908 
909 //-----------------------------------------------------------------------------
910 // Function : Region::getDoNothingFlag
911 // Purpose :
912 // Special Notes :
913 // Scope : public
914 // Creator : Eric Keiter
915 // Creation Date : 5/25/10
916 //-----------------------------------------------------------------------------
918 {
919  return regData.doNothing;
920 }
921 
922 //-----------------------------------------------------------------------------
923 // Function : Region::getBreakTime
924 // Purpose : Return next breakpoint time from reaction network
925 // Special Notes :
926 //
927 //
928 // Scope : public
929 // Creator : Tom Russo
930 // Creation Date : 8/4/06
931 //-----------------------------------------------------------------------------
933 {
934  return (theReactions.getBreakpointTime());
935 }
936 
937 //-----------------------------------------------------------------------------
938 // Function : Region::updateIntermediateVars
939 // Purpose :
940 // Special Notes :
941 //
942 // For reaction kinetics, all we have to do here is copy the concentrations
943 // out of the solution vector and into the temp storage
944 //
945 // Scope : public
946 // Creator : Eric R. Keiter
947 // Creation Date : 7/19/06
948 //-----------------------------------------------------------------------------
950  ( double * solVector, double * oldSolVector, double time)
951 {
952  if (baseReactionIndex != -1)
953  {
954  int rSize = theReactions.getNumSpecies();
955  if (tempConcentrations.size() != rSize)
956  {
957  tempConcentrations.clear();
958  tempConcentrations.resize(rSize,0.0);
959  }
960 
961  for (int i=0;i<rSize;++i)
962  {
963  tempConcentrations[i] = solVector[li_Concentrations[i]];
964  }
965 
966  // Now update the imposed time-dependent generation rates:
967  double scalar= ((variablesScaledFlag)?(t0/C0):(1.0));
968  theReactions.setSimTime(time);
969  theReactions.setSourceScaleFac(scalar);
970 
971  // Now compute ddt and jac for later use in the various loads
972  if (ddt.size() != rSize)
973  {
974  ddt.clear();
975  ddt.resize(rSize,0.0);
976  }
977  else
978  {
979  for (int i=0;i<rSize;++i)
980  {
981  ddt[i]=0.0;
982  }
983  }
984  theReactions.getDdt( tempConcentrations, theConstantConcentrations, ddt);
985 
986  // Jacobian
987  if (tempJac.size() != rSize)
988  {
989  tempJac.clear();
990  tempJac.resize(rSize);
991  for (int i=0; i<rSize; ++i)
992  {
993  tempJac[i].resize(rSize,0.0);
994  }
995  }
996  else
997  {
998  for (int i=0;i<rSize;++i)
999  {
1000  for (int j=0;j<rSize;++j)
1001  {
1002  tempJac[i][j]=0.0;
1003  }
1004  }
1005  }
1006 
1007  theReactions.getJac( tempConcentrations, theConstantConcentrations, tempJac);
1008  }
1009 }
1010 
1011 //-----------------------------------------------------------------------------
1012 // Function : Region::loadDAEQVector
1013 // Purpose :
1014 // Special Notes :
1015 // Scope : public
1016 // Creator : Eric R. Keiter
1017 // Creation Date : 7/21/06
1018 //-----------------------------------------------------------------------------
1019 bool Region::loadDAEQVector (double * qVec)
1020 {
1021 
1022  // ERK: The Q-vector must be loaded! Not loading during DCOP is a mistake!
1023  //
1024  // The Q-vector does not get summed into the residual during the DCOP. However,
1025  // it has to be computed during the DCOP, or else dQ/dt will be enormous in the
1026  // first time step out of the DCOP. (it will be (Q_1 - 0.0)/dt rather than (Q_1-Q_0)/dt.
1027  //
1028  // dQdt matrix does get summed into the jacobian, however, and this is because the
1029  // for some devices (particularly the stand-alone capacitor), excluding dQdx will result
1030  // in a singular jacobian.
1031  //
1032  // Note that this term will appear to cause the numerical jacobian test to fail for dQdx
1033  // during the DCOP. This is not a meaningful failure. The dQdx jacobian test should be turned
1034  // off for the DCOP phase.
1035 
1036  //if (!solState.dcopFlag)
1037  {
1038  if (baseReactionIndex != -1)
1039  {
1040  int rSize=theReactions.getNumSpecies();
1041 
1042  for (int i=0;i<rSize;++i)
1043  {
1044  double val = tempConcentrations[i];
1045  if (variablesScaledFlag)
1046  {
1047  val *= t0; // need to double-check this.
1048  }
1049  qVec[li_Concentrations[i]] += val;
1050  }
1051  }
1052  }
1053 
1054  return true;
1055 }
1056 
1057 
1058 //-----------------------------------------------------------------------------
1059 // Function : Region::loadDAEFVector
1060 // Purpose :
1061 // Special Notes :
1062 // Scope : public
1063 // Creator : Eric R. Keiter
1064 // Creation Date : 7/21/06
1065 //-----------------------------------------------------------------------------
1066 bool Region::loadDAEFVector (double * fVec)
1067 {
1068  if (baseReactionIndex != -1)
1069  {
1070  int rSize=theReactions.getNumSpecies();
1071 
1073  {
1074  // satisfy initial condition at dcop
1075  for (int i=0;i<rSize;++i)
1076  {
1078  }
1079  }
1080  else
1081  {
1082  // ddt from reaction rate should be equal to ddt from time integrator
1083  for (int i=0;i<rSize;++i)
1084  {
1085  fVec[li_Concentrations[i]] += (-ddt[i]);
1086  }
1087  }
1088  }
1089 
1090  return true;
1091 }
1092 
1093 //-----------------------------------------------------------------------------
1094 // Function : Region::loadDAEdFdxdV
1095 // Purpose :
1096 // Special Notes :
1097 // Scope : public
1098 // Creator : Eric R. Keiter
1099 // Creation Date : 10/26/06
1100 //-----------------------------------------------------------------------------
1101 bool Region::loadDAEdFdxdV (double * dfdxdv,double vdiff)
1102 {
1103  return true;
1104 }
1105 
1106 //-----------------------------------------------------------------------------
1107 // Function : Region::loadDAEdQdx
1108 // Purpose :
1109 // Special Notes :
1110 // Scope : public
1111 // Creator : Eric R. Keiter
1112 // Creation Date : 7/21/06
1113 //-----------------------------------------------------------------------------
1114 bool Region::loadDAEdQdx (N_LAS_Matrix & dqdx)
1115 {
1116 
1117  if (baseReactionIndex != -1)
1118  {
1119  if ( !(solState.dcopFlag || regData.doNothing) )
1120  {
1121  double val = ((variablesScaledFlag)?(t0):(1.0));
1122  int rSize = theReactions.getNumSpecies();
1123  for (int i=0;i<rSize; ++i)
1124  {
1125  *(dqdxConcEquConcVarPtrs[i][i]) += val;
1126  }
1127  }
1128  }
1129 
1130  return true;
1131 }
1132 
1133 //-----------------------------------------------------------------------------
1134 // Function : Region::loadDAEdFdx
1135 // Purpose :
1136 // Special Notes :
1137 // Scope : public
1138 // Creator : Eric R. Keiter
1139 // Creation Date : 7/21/06
1140 //-----------------------------------------------------------------------------
1141 bool Region::loadDAEdFdx (N_LAS_Matrix & dfdx)
1142 {
1143  if (baseReactionIndex != -1)
1144  {
1145  int rSize = theReactions.getNumSpecies();
1147  {
1148  // jacobian for dcop is just ones on the diagonals, nothing else
1149  for (int i=0; i<rSize; ++i)
1150  {
1151  *(dfdxConcEquConcVarPtrs[i][i]) += 1.0;
1152  }
1153  }
1154  else
1155  {
1156  for (int i=0;i<rSize; ++i)
1157  {
1158  for (int j=0;j<rSize; ++j)
1159  {
1160  double val = (-tempJac[i][j]);
1161  *(dfdxConcEquConcVarPtrs[i][j]) += val;
1162  }
1163  }
1164  }
1165  }
1166 
1167  return true;
1168 }
1169 
1170 //-----------------------------------------------------------------------------
1171 // Function : Region::updateSecondaryState
1172 // Purpose : Obtains time derivatives of concentrations from
1173 // time integrator
1174 // Special Notes :
1175 // Scope : public
1176 // Creator : Eric R. Keiter
1177 // Creation Date : 7/21/06
1178 //-----------------------------------------------------------------------------
1179 bool Region::updateSecondaryState (double * staDeriv)
1180 {
1181  if (baseReactionIndex != -1)
1182  {
1183  int rSize = theReactions.getNumSpecies();
1184  if (tempConcentrationDerivs.size() != rSize)
1185  {
1186  tempConcentrationDerivs.clear();
1187  tempConcentrationDerivs.resize(rSize,0.0);
1188  }
1189 
1190  for (int i=0;i<rSize;++i)
1191  {
1193 
1194  // If the variablesScaledFlag is true, then the concentrations
1195  // are already scaled, but the time is not.
1196  if (variablesScaledFlag)
1197  {
1199  }
1200  }
1201  }
1202 
1203  return true;
1204 }
1205 
1206 //-----------------------------------------------------------------------------
1207 // Function : Region::haveAnyReactions()
1208 // Purpose :
1209 // Special Notes :
1210 //
1211 // TVR: This one is a legacy of how I was keeping track of when
1212 // the network was initialized and jacobian set up. All the places
1213 // where this baseReactionIndex != -1 occur were really only checking
1214 // that the thing had been initialized.
1215 //
1216 // ERK: updated to include a test for "do nothing" flag.
1217 //
1218 // Scope : public
1219 // Creator : Eric R. Keiter, SNL
1220 // Creation Date : 05/22/10
1221 //-----------------------------------------------------------------------------
1223 {
1224  bool retVal = (baseReactionIndex != -1);
1225 
1226  if (regData.doNothing)
1227  {
1228  retVal = false;
1229  }
1230 
1231  return retVal;
1232 }
1233 
1234 //-----------------------------------------------------------------------------
1235 // Function : Region::getNumIntVars
1236 //
1237 // Purpose : Return the number of internal variables (solution vars)
1238 // this region is adding to the system.
1239 //
1240 // Special Notes : The number of internal variables is comprised of the
1241 // number of species in the reaction network.
1242 //
1243 // Scope : public
1244 //
1245 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
1246 // Creation Date : 10/24/06
1247 //-----------------------------------------------------------------------------
1249 {
1250  int hInt=0;
1251  int numSpeciesVars=0;
1252 
1253  if (!(regData.doNothing))
1254  {
1255  numSpeciesVars=getNumSpecies();
1256  }
1257 
1258  return (numSpeciesVars+hInt);
1259 }
1260 
1261 //-----------------------------------------------------------------------------
1262 // Function : Region::loadDeviceMask
1263 // Purpose :
1264 // Special Notes :
1265 // Scope : public
1266 // Creator : Eric Keiter, SNL, Electrical and Microsystems Modeling
1267 // Creation Date : 5/15/07
1268 //-----------------------------------------------------------------------------
1269 bool Region::loadDeviceMask (N_LAS_Vector & mask)
1270 {
1271  return true;
1272 }
1273 
1274 } // namespace Device
1275 } // namespace Xyce