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.19 $
40 //
41 // Revision Date : $Date: 2014/05/19 15:49:14 $
42 //
43 // Current Owner : $Author: dgbaur $
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.getEncodedName().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  if ( !(regData.doNothing) )
759  {
760  if (baseReactionIndex != -1)
761  {
762  int rSize=theReactions.getNumSpecies();
763  for (int i=0;i<rSize;++i)
764  {
765  std::string speciesName=theReactions.getSpeciesName(i);
766  intNameMap[li_Concentrations[i]] = spiceInternalName(getName(), "Conc_" + speciesName);
767  }
768  }
769  }
770 }
771 
772 //-----------------------------------------------------------------------------
773 // Function : Region::registerStateLIDs
774 // Purpose :
775 // Special Notes :
776 // Scope : public
777 // Creator : Eric R. Keiter
778 // Creation Date : 7/20/06
779 //-----------------------------------------------------------------------------
781  (const std::vector<int> & staLIDVec, int & i)
782 {
783  if (baseReactionIndex != -1)
784  {
785  int rSize = theReactions.getNumSpecies();
786  li_state_Concentrations.resize(rSize);
787  for (int j=0;j<rSize;++j)
788  {
789  li_state_Concentrations[j]=staLIDVec[i++];
790  }
791  }
792 }
793 
794 //-----------------------------------------------------------------------------
795 // Function : Region::registerJacLIDs
796 // Purpose :
797 // Special Notes :
798 // Scope : public
799 // Creator : Eric R. Keiter
800 // Creation Date : 7/20/06
801 //-----------------------------------------------------------------------------
803  ( const std::vector< std::vector<int> > & jacLIDVec,
804  const std::vector<int> &map,
805  const std::vector< std::vector<int> > &map2
806  )
807 {
808  if ( !(regData.doNothing) )
809  {
810  if (baseReactionIndex != -1)
811  {
812  int rSize = theReactions.getNumSpecies();
813  AConcentrationEquConcentrationNodeOffsets.clear();
814  AConcentrationEquAuxNodeOffsets.clear();
815 
816  AConcentrationEquConcentrationNodeOffsets.resize(rSize);
817  AConcentrationEquAuxNodeOffsets.resize(rSize);
818 
819  for (int i=0;i<rSize;++i)
820  {
821  AConcentrationEquConcentrationNodeOffsets[i].resize(rSize);
822  for (int j=0;j<rSize;++j)
823  {
824  AConcentrationEquConcentrationNodeOffsets[i][j]=
825  jacLIDVec[map[baseReactionIndex+i]][map2[baseReactionIndex+i][j]];
826  }
827 
828 #if 0
829  int bRI = baseReactionIndex;
830  AConcentrationEquAuxNodeOffsets[i].resize(2);
831  for (int j=0; j<2; ++j)
832  {
833  AConcentrationEquAuxNodeOffsets[i][j]=
834  jacLIDVec[map[bRI+i]][map2[bRI+i][rSize+j]];
835  }
836 #endif
837  }
838  }
839  }
840 
841 }
842 
843 //-----------------------------------------------------------------------------
844 // Function : Region::setupPointers()
845 // Purpose :
846 // Special Notes :
847 // Scope : public
848 // Creator : Eric R. Keiter, SNL
849 // Creation Date : 5/19/10
850 //-----------------------------------------------------------------------------
851 void Region::setupPointers (N_LAS_Matrix & dfdx, N_LAS_Matrix & dqdx)
852 {
853  if ( !(regData.doNothing) )
854  {
855  int rSize = theReactions.getNumSpecies();
856 
857  dfdxConcEquConcVarPtrs.clear();
858  dfdxConcEquConcVarPtrs.resize(rSize);
859 
860  dqdxConcEquConcVarPtrs.clear();
861  dqdxConcEquConcVarPtrs.resize(rSize);
862 
863 #if 0
864  dfdxConcEquAuxVarPtrs.clear();
865  dfdxConcEquAuxVarPtrs.resize(rSize);
866 
867  dqdxConcEquAuxVarPtrs.clear();
868  dqdxConcEquAuxVarPtrs.resize(rSize);
869 #endif
870 
871  for (int i=0;i<rSize;++i)
872  {
873  dfdxConcEquConcVarPtrs[i].resize(rSize,0);
874  dqdxConcEquConcVarPtrs[i].resize(rSize,0);
875 
876  for (int j=0;j<rSize; ++j)
877  {
878  int lidRow = li_Concentrations[i];
879  int lidCol = li_Concentrations[j];
880 
881  double * dfdxPtr = dfdx.returnRawEntryPointer (lidRow, lidCol);
882  dfdxConcEquConcVarPtrs[i][j] = dfdxPtr;
883 
884  double * dqdxPtr = dqdx.returnRawEntryPointer (lidRow, lidCol);
885  dqdxConcEquConcVarPtrs[i][j] = dqdxPtr;
886  }
887 
888 #if 0
889  dfdxConcEquAuxVarPtrs[i].resize(2,0);
890  dqdxConcEquAuxVarPtrs[i].resize(2,0);
891  for (int j=0;j<2; ++j)
892  {
893  int lidRow = li_Concentrations[i];
894  int coloffset = AConcentrationEquAuxNodeOffsets[i][j];
895 
896  dfdxConcEquAuxVarPtrs[i][j] = &(dfdx[lidRow][coloffset]);
897  dqdxConcEquAuxVarPtrs[i][j] = &(dqdx[lidRow][coloffset]);
898  }
899 #endif
900  }
901  }
902 }
903 
904 //-----------------------------------------------------------------------------
905 // Function : Region::getDoNothingFlag
906 // Purpose :
907 // Special Notes :
908 // Scope : public
909 // Creator : Eric Keiter
910 // Creation Date : 5/25/10
911 //-----------------------------------------------------------------------------
913 {
914  return regData.doNothing;
915 }
916 
917 //-----------------------------------------------------------------------------
918 // Function : Region::getBreakTime
919 // Purpose : Return next breakpoint time from reaction network
920 // Special Notes :
921 //
922 //
923 // Scope : public
924 // Creator : Tom Russo
925 // Creation Date : 8/4/06
926 //-----------------------------------------------------------------------------
928 {
929  return (theReactions.getBreakpointTime());
930 }
931 
932 //-----------------------------------------------------------------------------
933 // Function : Region::updateIntermediateVars
934 // Purpose :
935 // Special Notes :
936 //
937 // For reaction kinetics, all we have to do here is copy the concentrations
938 // out of the solution vector and into the temp storage
939 //
940 // Scope : public
941 // Creator : Eric R. Keiter
942 // Creation Date : 7/19/06
943 //-----------------------------------------------------------------------------
945  ( double * solVector, double * oldSolVector, double time)
946 {
947  if (baseReactionIndex != -1)
948  {
949  int rSize = theReactions.getNumSpecies();
950  if (tempConcentrations.size() != rSize)
951  {
952  tempConcentrations.clear();
953  tempConcentrations.resize(rSize,0.0);
954  }
955 
956  for (int i=0;i<rSize;++i)
957  {
958  tempConcentrations[i] = solVector[li_Concentrations[i]];
959  }
960 
961  // Now update the imposed time-dependent generation rates:
962  double scalar= ((variablesScaledFlag)?(t0/C0):(1.0));
963  theReactions.setSimTime(time);
964  theReactions.setSourceScaleFac(scalar);
965 
966  // Now compute ddt and jac for later use in the various loads
967  if (ddt.size() != rSize)
968  {
969  ddt.clear();
970  ddt.resize(rSize,0.0);
971  }
972  else
973  {
974  for (int i=0;i<rSize;++i)
975  {
976  ddt[i]=0.0;
977  }
978  }
979  theReactions.getDdt( tempConcentrations, theConstantConcentrations, ddt);
980 
981  // Jacobian
982  if (tempJac.size() != rSize)
983  {
984  tempJac.clear();
985  tempJac.resize(rSize);
986  for (int i=0; i<rSize; ++i)
987  {
988  tempJac[i].resize(rSize,0.0);
989  }
990  }
991  else
992  {
993  for (int i=0;i<rSize;++i)
994  {
995  for (int j=0;j<rSize;++j)
996  {
997  tempJac[i][j]=0.0;
998  }
999  }
1000  }
1001 
1002  theReactions.getJac( tempConcentrations, theConstantConcentrations, tempJac);
1003  }
1004 }
1005 
1006 //-----------------------------------------------------------------------------
1007 // Function : Region::loadDAEQVector
1008 // Purpose :
1009 // Special Notes :
1010 // Scope : public
1011 // Creator : Eric R. Keiter
1012 // Creation Date : 7/21/06
1013 //-----------------------------------------------------------------------------
1014 bool Region::loadDAEQVector (double * qVec)
1015 {
1016 
1017  // ERK: The Q-vector must be loaded! Not loading during DCOP is a mistake!
1018  //
1019  // The Q-vector does not get summed into the residual during the DCOP. However,
1020  // it has to be computed during the DCOP, or else dQ/dt will be enormous in the
1021  // first time step out of the DCOP. (it will be (Q_1 - 0.0)/dt rather than (Q_1-Q_0)/dt.
1022  //
1023  // dQdt matrix does get summed into the jacobian, however, and this is because the
1024  // for some devices (particularly the stand-alone capacitor), excluding dQdx will result
1025  // in a singular jacobian.
1026  //
1027  // Note that this term will appear to cause the numerical jacobian test to fail for dQdx
1028  // during the DCOP. This is not a meaningful failure. The dQdx jacobian test should be turned
1029  // off for the DCOP phase.
1030 
1031  //if (!solState.dcopFlag)
1032  {
1033  if (baseReactionIndex != -1)
1034  {
1035  int rSize=theReactions.getNumSpecies();
1036 
1037  for (int i=0;i<rSize;++i)
1038  {
1039  double val = tempConcentrations[i];
1040  if (variablesScaledFlag)
1041  {
1042  val *= t0; // need to double-check this.
1043  }
1044  qVec[li_Concentrations[i]] += val;
1045  }
1046  }
1047  }
1048 
1049  return true;
1050 }
1051 
1052 
1053 //-----------------------------------------------------------------------------
1054 // Function : Region::loadDAEFVector
1055 // Purpose :
1056 // Special Notes :
1057 // Scope : public
1058 // Creator : Eric R. Keiter
1059 // Creation Date : 7/21/06
1060 //-----------------------------------------------------------------------------
1061 bool Region::loadDAEFVector (double * fVec)
1062 {
1063  if (baseReactionIndex != -1)
1064  {
1065  int rSize=theReactions.getNumSpecies();
1066 
1068  {
1069  // satisfy initial condition at dcop
1070  for (int i=0;i<rSize;++i)
1071  {
1073  }
1074  }
1075  else
1076  {
1077  // ddt from reaction rate should be equal to ddt from time integrator
1078  for (int i=0;i<rSize;++i)
1079  {
1080  fVec[li_Concentrations[i]] += (-ddt[i]);
1081  }
1082  }
1083  }
1084 
1085  return true;
1086 }
1087 
1088 //-----------------------------------------------------------------------------
1089 // Function : Region::loadDAEdFdxdV
1090 // Purpose :
1091 // Special Notes :
1092 // Scope : public
1093 // Creator : Eric R. Keiter
1094 // Creation Date : 10/26/06
1095 //-----------------------------------------------------------------------------
1096 bool Region::loadDAEdFdxdV (double * dfdxdv,double vdiff)
1097 {
1098  return true;
1099 }
1100 
1101 //-----------------------------------------------------------------------------
1102 // Function : Region::loadDAEdQdx
1103 // Purpose :
1104 // Special Notes :
1105 // Scope : public
1106 // Creator : Eric R. Keiter
1107 // Creation Date : 7/21/06
1108 //-----------------------------------------------------------------------------
1109 bool Region::loadDAEdQdx (N_LAS_Matrix & dqdx)
1110 {
1111 
1112  if (baseReactionIndex != -1)
1113  {
1114  if ( !(solState.dcopFlag || regData.doNothing) )
1115  {
1116  double val = ((variablesScaledFlag)?(t0):(1.0));
1117  int rSize = theReactions.getNumSpecies();
1118  for (int i=0;i<rSize; ++i)
1119  {
1120  *(dqdxConcEquConcVarPtrs[i][i]) += val;
1121  }
1122  }
1123  }
1124 
1125  return true;
1126 }
1127 
1128 //-----------------------------------------------------------------------------
1129 // Function : Region::loadDAEdFdx
1130 // Purpose :
1131 // Special Notes :
1132 // Scope : public
1133 // Creator : Eric R. Keiter
1134 // Creation Date : 7/21/06
1135 //-----------------------------------------------------------------------------
1136 bool Region::loadDAEdFdx (N_LAS_Matrix & dfdx)
1137 {
1138  if (baseReactionIndex != -1)
1139  {
1140  int rSize = theReactions.getNumSpecies();
1142  {
1143  // jacobian for dcop is just ones on the diagonals, nothing else
1144  for (int i=0; i<rSize; ++i)
1145  {
1146  *(dfdxConcEquConcVarPtrs[i][i]) += 1.0;
1147  }
1148  }
1149  else
1150  {
1151  for (int i=0;i<rSize; ++i)
1152  {
1153  for (int j=0;j<rSize; ++j)
1154  {
1155  double val = (-tempJac[i][j]);
1156  *(dfdxConcEquConcVarPtrs[i][j]) += val;
1157  }
1158  }
1159  }
1160  }
1161 
1162  return true;
1163 }
1164 
1165 //-----------------------------------------------------------------------------
1166 // Function : Region::updateSecondaryState
1167 // Purpose : Obtains time derivatives of concentrations from
1168 // time integrator
1169 // Special Notes :
1170 // Scope : public
1171 // Creator : Eric R. Keiter
1172 // Creation Date : 7/21/06
1173 //-----------------------------------------------------------------------------
1174 bool Region::updateSecondaryState (double * staDeriv)
1175 {
1176  if (baseReactionIndex != -1)
1177  {
1178  int rSize = theReactions.getNumSpecies();
1179  if (tempConcentrationDerivs.size() != rSize)
1180  {
1181  tempConcentrationDerivs.clear();
1182  tempConcentrationDerivs.resize(rSize,0.0);
1183  }
1184 
1185  for (int i=0;i<rSize;++i)
1186  {
1188 
1189  // If the variablesScaledFlag is true, then the concentrations
1190  // are already scaled, but the time is not.
1191  if (variablesScaledFlag)
1192  {
1194  }
1195  }
1196  }
1197 
1198  return true;
1199 }
1200 
1201 //-----------------------------------------------------------------------------
1202 // Function : Region::haveAnyReactions()
1203 // Purpose :
1204 // Special Notes :
1205 //
1206 // TVR: This one is a legacy of how I was keeping track of when
1207 // the network was initialized and jacobian set up. All the places
1208 // where this baseReactionIndex != -1 occur were really only checking
1209 // that the thing had been initialized.
1210 //
1211 // ERK: updated to include a test for "do nothing" flag.
1212 //
1213 // Scope : public
1214 // Creator : Eric R. Keiter, SNL
1215 // Creation Date : 05/22/10
1216 //-----------------------------------------------------------------------------
1218 {
1219  bool retVal = (baseReactionIndex != -1);
1220 
1221  if (regData.doNothing)
1222  {
1223  retVal = false;
1224  }
1225 
1226  return retVal;
1227 }
1228 
1229 //-----------------------------------------------------------------------------
1230 // Function : Region::getNumIntVars
1231 //
1232 // Purpose : Return the number of internal variables (solution vars)
1233 // this region is adding to the system.
1234 //
1235 // Special Notes : The number of internal variables is comprised of the
1236 // number of species in the reaction network.
1237 //
1238 // Scope : public
1239 //
1240 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
1241 // Creation Date : 10/24/06
1242 //-----------------------------------------------------------------------------
1244 {
1245  int hInt=0;
1246  int numSpeciesVars=0;
1247 
1248  if (!(regData.doNothing))
1249  {
1250  numSpeciesVars=getNumSpecies();
1251  }
1252 
1253  return (numSpeciesVars+hInt);
1254 }
1255 
1256 //-----------------------------------------------------------------------------
1257 // Function : Region::loadDeviceMask
1258 // Purpose :
1259 // Special Notes :
1260 // Scope : public
1261 // Creator : Eric Keiter, SNL, Electrical and Microsystems Modeling
1262 // Creation Date : 5/15/07
1263 //-----------------------------------------------------------------------------
1264 bool Region::loadDeviceMask (N_LAS_Vector & mask)
1265 {
1266  return true;
1267 }
1268 
1269 } // namespace Device
1270 } // namespace Xyce