Xyce  6.1
N_DEV_2DPDE_DAE.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-2015 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_2DPDE_DAE.C,v $
27 //
28 // Purpose : This file contains a lot of the
29 // implementation of the instance class for the two
30 // dimensional PDE based semiconductor device.
31 //
32 // Functions pertaining to the initial setup are in other
33 // files, as are functions relating to mesh handling and
34 // parameter handling.
35 //
36 // Special Notes :
37 //
38 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
39 //
40 // Creation Date : 07/05/03
41 //
42 // Revision Information:
43 // ---------------------
44 //
45 // Revision Number: $Revision: 1.34 $
46 //
47 // Revision Date : $Date: 2015/04/27 17:50:45 $
48 //
49 // Current Owner : $Author: erkeite $
50 //-------------------------------------------------------------------------
51 
52 #include <Xyce_config.h>
53 
54 // ---------- Standard Includes ----------
55 #include <iostream>
56 
57 // ---------- Xyce Includes ----------
58 #include <N_DEV_2DPDE.h>
59 #include <N_DEV_SolverState.h>
60 #include <N_DEV_ExternData.h>
61 #include <N_DEV_DeviceOptions.h>
62 #include <N_DEV_MatrixLoadData.h>
63 #include <N_DEV_PDE_2DMesh.h>
64 #include <N_DEV_SourceData.h>
65 
66 #include <N_LAS_Vector.h>
67 #include <N_LAS_Matrix.h>
68 #include <N_LAS_System.h>
69 #include <N_LAS_Builder.h>
70 
71 namespace Xyce {
72 namespace Device {
73 namespace TwoDPDE {
74 
75 //-----------------------------------------------------------------------------
76 // Function : Instance::loadDAEFVector
77 // Purpose :
78 // Special Notes :
79 // Scope : public
80 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
81 // Creation Date : 6/21/05
82 //-----------------------------------------------------------------------------
84 {
85  bool bsuccess = true;
86  bool bs1;
87 
88  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
89  {
90  Xyce::dout() << "loadDAEFVector: doubleDCOPStep="<<getSolverState().doubleDCOPStep;
91  if (getSolverState().dcopFlag)
92  {
93  Xyce::dout() << " DCOP load" <<std::endl;
94  }
95  else
96  {
97  Xyce::dout() << " Transient load" <<std::endl;
98  }
99  }
100 
101  if ((getSolverState().dcopFlag) && getSolverState().doubleDCOPStep == 0)
102  {
103  equationSet = 0;
104  bs1 = loadDAEFNonlinPoisson ();
105  }
106  else
107  {
108  equationSet = 1;
109 
110  if (getSolverState().twoLevelNewtonCouplingMode==Nonlinear::INNER_PROBLEM ||
111  getSolverState().twoLevelNewtonCouplingMode==Nonlinear::FULL_PROBLEM)
112  {
113  bs1 = loadDAEFDDFormulation ();
114  }
115  else if (getSolverState().twoLevelNewtonCouplingMode==Nonlinear::OUTER_PROBLEM)
116  {
118  }
119  else
120  {
121  std::string msg = "Instance::loadDAEFVector."
122  "Invalid coupling Mode";
123  N_ERH_ErrorMgr::report ( N_ERH_ErrorMgr::DEV_FATAL,msg);
124  }
125  }
126 
127  return (bsuccess && bs1);
128 }
129 
130 //-----------------------------------------------------------------------------
131 // Function : Instance::loadDAEFNonlinPoisson
132 // Purpose : Loads the F-vector the nonlinear poisson calculation.
133 //
134 // Special Notes : This should be identical to the original loadRHS function,
135 // for the nonlinear poisson. All of that goes into the
136 // FVector, but with the opposite sign.
137 //
138 // Scope : public
139 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
140 // Creation Date : 6/21/05
141 //-----------------------------------------------------------------------------
143 {
144  return loadVecNLPoisson ( -1.0, extData.daeFVectorPtr );
145 }
146 
147 //-----------------------------------------------------------------------------
148 // Function : Instance::loadDAEFDDFormulation
149 // Purpose : This function should be called from the loadDAEFVector
150 // function when solving the drift-diffusion equations.
151 // Special Notes :
152 //
153 // Scope : private
154 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
155 // Creation Date : 6/21/05
156 //-----------------------------------------------------------------------------
158 {
159  // calcTerminalCurrents needs to be here b/c it is otherwise
160  // called from updateSecondaryState
162  return loadVecDDForm (-1.0,0.0, extData.daeFVectorPtr);
163 }
164 
165 //-----------------------------------------------------------------------------
166 // Function : Instance::loadDAEFExtractedConductance
167 // Purpose :
168 // Special Notes :
169 // Scope : private
170 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
171 // Creation Date : 6/21/05
172 //-----------------------------------------------------------------------------
174 {
175  bool bsuccess = true;
176  bool bs1 = true;
177  int Vrow, Nrow, Prow;
178  double coef;
179 
180  // KCL equations for the various connecting terminals:
181  std::vector<DeviceInterfaceNode>::iterator firstDI = dIVec.begin();
182  std::vector<DeviceInterfaceNode>::iterator lastDI = dIVec.end ();
183  std::vector<DeviceInterfaceNode>::iterator iterDI = firstDI;
184 
185  int iRow = 0;
186  for (;iterDI!=lastDI;++iterDI, ++iRow)
187  {
188  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
189  {
190  Xyce::dout() << "name = " << iterDI->eName;
191  Xyce::dout() << " iRow = " << iRow << std::endl;
192  }
193 
194  coef = iterDI->currentSum;
195 
196  double voltLimFac = 0.0;
197  if (getDeviceOptions().voltageLimiterFlag && voltLimFlag)
198  {
199  int iCol;
200  for (iCol=0; iCol < numElectrodes ; ++iCol)
201  {
202  if (dIVec[iCol].gid == -1) continue;
203 
204  double vdiff = dIVec[iCol].Vckt_final - dIVec[iCol].Vckt_orig;
205 
206  vdiff *= scalingVars.V0;
207 
208  voltLimFac += vdiff * condVec[iRow][iCol];
209 
210  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
211  {
212  Xyce::dout() << "iCol = " << iCol;
213  Xyce::dout() << " vdiff = " << vdiff;
214  Xyce::dout() << " cond = " << condVec[iRow][iCol];
215  Xyce::dout() << " voltLimFac = " << voltLimFac << std::endl;
216  }
217  }
218  }
219 
220  if( useVectorGIDFlag )
221  {
222  if (iterDI->gid != -1)
223  {
224  bs1 = extData.daeFVectorPtr->sumElementByGlobalIndex
225  (iterDI->gid, coef - voltLimFac, 0);
226  bsuccess = bsuccess && bs1;
227 
228  if (DEBUG_DEVICE)
229  {
230  bs1 = extData.JdxpVectorPtr->sumElementByGlobalIndex
231  (iterDI->gid, voltLimFac, 0);
232  bsuccess = bsuccess && bs1;
233  }
234  }
235  }
236  else
237  {
238  (*extData.daeFVectorPtr)[iterDI->lid] += coef - voltLimFac;
239 
240  if (DEBUG_DEVICE)
241  {
242  (*extData.JdxpVectorPtr)[iterDI->lid] += voltLimFac;
243  }
244  }
245 
246  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
247  {
248  Xyce::dout() << "KCL for "<< iterDI->eName << ":\n";
249  Xyce::dout() << " row = " << iterDI->gid << "\n";
250  Xyce::dout() << "currentSum = " << coef << "\n";
251  Xyce::dout() << "voltLimFac = " << voltLimFac << std::endl;
252  }
253  } // end of DI loop
254 
255  // Load in the zeros...
256  for (int i=0;i<numMeshPoints;++i)
257  {
258 #ifdef Xyce_NEW_BC
259  if (boundarySten[i]) continue;
260 #endif // Xyce_NEW_BC
261 
262  Vrow = Vrowarray[i];
263  Nrow = Nrowarray[i];
264  Prow = Prowarray[i];
265 
266  if( useVectorGIDFlag )
267  {
268  if (Vrow != -1)
269  {
270  bs1 = extData.daeFVectorPtr->sumElementByGlobalIndex(Vrow, 0.0, 0);
271  bsuccess = bsuccess && bs1;
272  }
273  }
274  else
275  {
276  (*extData.daeFVectorPtr)[Vrow] = 0.0;
277  }
278 
279  if( useVectorGIDFlag )
280  {
281  if (Nrow != -1)
282  {
283  bs1 = extData.daeFVectorPtr->sumElementByGlobalIndex(Nrow, 0.0, 0);
284  bsuccess = bsuccess && bs1;
285  }
286  }
287  else
288  {
289  (*extData.daeFVectorPtr)[Nrow] = 0.0;
290  }
291 
292  if( useVectorGIDFlag )
293  {
294  if (Prow != -1)
295  {
296  bs1 = extData.daeFVectorPtr->sumElementByGlobalIndex(Prow, 0.0, 0);
297  bsuccess = bsuccess && bs1;
298  }
299  }
300  else
301  {
302  (*extData.daeFVectorPtr)[Prow] = 0.0;
303  }
304  }
305 
306  return bsuccess;
307 }
308 
309 //-----------------------------------------------------------------------------
310 // Function : Instance::loadDAEQVector
311 // Purpose :
312 // Special Notes :
313 // Scope : public
314 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
315 // Creation Date : 6/21/05
316 //-----------------------------------------------------------------------------
318 {
319  bool bsuccess = true;
320  bool bs1;
321 
322  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
323  {
324  Xyce::dout() << "loadDAEQVector: doubleDCOPStep="<<getSolverState().doubleDCOPStep;
325  if (getSolverState().dcopFlag) Xyce::dout() << " DCOP load" <<std::endl;
326  else Xyce::dout() << " Transient load" <<std::endl;
327  }
328 
329  if ((getSolverState().dcopFlag) && getSolverState().doubleDCOPStep == 0)
330  {
331  equationSet = 0;
332  bs1 = true; // no-op
333  }
334  else
335  {
336  equationSet = 1;
337 
338  if (getSolverState().twoLevelNewtonCouplingMode==Nonlinear::INNER_PROBLEM ||
339  getSolverState().twoLevelNewtonCouplingMode==Nonlinear::FULL_PROBLEM)
340  {
341  bs1 = loadDAEQDDFormulation ();
342  }
343  else if (getSolverState().twoLevelNewtonCouplingMode==Nonlinear::OUTER_PROBLEM)
344  {
346  }
347  else
348  {
349  std::string msg = "Instance::loadDAEQVector."
350  "Invalid coupling Mode";
351  N_ERH_ErrorMgr::report ( N_ERH_ErrorMgr::DEV_FATAL,msg);
352  }
353  }
354 
355  return (bsuccess && bs1);
356 }
357 
358 
359 //-----------------------------------------------------------------------------
360 // Function : Instance::loadDAEQDDFormulation
361 // Purpose :
362 // Special Notes :
363 // Scope : private
364 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
365 // Creation Date : 6/21/05
366 //-----------------------------------------------------------------------------
368 {
369  bool bsuccess = true;
370  bool bs1 = true;
371 
372  Linear::Vector * vecPtr = extData.daeQVectorPtr;
373 
374  int i;
375  int Nrow, Prow;
376 
377  // mesh points for the PDE problem:
378  for (i=0;i<numMeshPoints;++i)
379  {
380 
381  // skip boundary points, for both NEW_BC and old.
382  if (boundarySten[i]) continue;
383 
384  if( useVectorGIDFlag )
385  {
386  Nrow = Nrowarray[i];
387  Prow = Prowarray[i];
388 
389  bs1 = vecPtr->sumElementByGlobalIndex(Nrow, (-nnVec[i]*scalingVars.t0), 0);
390  bsuccess = bsuccess && bs1;
391 
392  bs1 = vecPtr->sumElementByGlobalIndex(Prow, (-npVec[i]*scalingVars.t0), 0);
393  bsuccess = bsuccess && bs1;
394  }
395  else
396  {
397  Nrow = li_Nrowarray[i];
398  Prow = li_Prowarray[i];
399  (*vecPtr)[Nrow] = -nnVec[i]*scalingVars.t0;
400  (*vecPtr)[Prow] = -npVec[i]*scalingVars.t0;
401  }
402 
403  }
404 
405  return bsuccess;
406 }
407 
408 //-----------------------------------------------------------------------------
409 // Function : Instance::loadDAEdFdx
410 // Purpose : This function performs an analytic Jacobian matrix load for
411 // the diode-pde class, for the case of solving a nonlinear
412 // poisson equation.
413 // Special Notes :
414 //
415 // Scope : private
416 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
417 // Creation Date : 6/21/05
418 //-----------------------------------------------------------------------------
420 {
421  bool bsuccess;
422 
423  if ((getSolverState().dcopFlag) && getSolverState().doubleDCOPStep == 0)
424  {
425  bsuccess = loadDAEdFdxNonlinPoisson ();
426  }
427  else
428  {
429  if (getSolverState().twoLevelNewtonCouplingMode==Nonlinear::INNER_PROBLEM ||
430  getSolverState().twoLevelNewtonCouplingMode==Nonlinear::FULL_PROBLEM)
431  {
432  bsuccess = loadDAEdFdxDDFormulation ();
433  }
434  else if (getSolverState().twoLevelNewtonCouplingMode==Nonlinear::OUTER_PROBLEM)
435  {
436  bsuccess = loadDAEdFdxExtractedConductance ();
437  }
438  else
439  {
440  Report::DevelFatal().in("Instance::loadDAEdFdx") << "Invalid coupling Mode" << numElectrodes;
441  }
442  }
443 
444  return bsuccess;
445 }
446 
447 //-----------------------------------------------------------------------------
448 // Function : Instance::loadDAEdFdxNonlinPoisson
449 // Purpose : This function performs an analytic Jacobian matrix load for
450 // the diode-pde class, for the case of solving a nonlinear
451 // poisson equation.
452 // Special Notes :
453 //
454 // Scope : private
455 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
456 // Creation Date : 6/21/05
457 //-----------------------------------------------------------------------------
459 {
461 }
462 
463 //-----------------------------------------------------------------------------
464 // Function : Instance::loadDAEdFdxDDFormulation
465 // Purpose :
466 // Special Notes :
467 // Scope : private
468 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
469 // Creation Date : 6/21/05
470 //-----------------------------------------------------------------------------
472 {
473  bool bsuccess = true;
474  bool bs1 = true;
475  // set up some of the partial derivative arrays:
476  bs1 = pdRecombination (); bsuccess = bsuccess && bs1;
477  bs1 = pdElectronCurrent (); bsuccess = bsuccess && bs1;
478  bs1 = pdHoleCurrent (); bsuccess = bsuccess && bs1;
479  bs1 = pdTerminalCurrents ();bsuccess = bsuccess && bs1;
480 
481  if ( !(getSolverState().twoLevelNewtonCouplingMode==Nonlinear::INNER_PROBLEM))
482  {
484  bsuccess = bsuccess && bs1;
485  }
486  else
487  {
489  bsuccess = bsuccess && bs1;
490  }
491 
492  bs1 = loadMatDDForm ( 0.0, extData.dFdxMatrixPtr );
493  bsuccess = bsuccess && bs1;
494 
495  return bsuccess;
496 }
497 
498 //-----------------------------------------------------------------------------
499 // Function : Instance::loadDAEdFdxExtractedConductance
500 // Purpose :
501 // Special Notes :
502 // Scope : private
503 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
504 // Creation Date : 6/21/05
505 //-----------------------------------------------------------------------------
507 {
508  bool bsuccess = true;
509  bool bs1 = true;
510 
511  Linear::Matrix & dFdx = *(extData.dFdxMatrixPtr);
512  Linear::Matrix * matPtr = extData.dFdxMatrixPtr;
513 
514  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
515  {
516  Xyce::dout() << std::endl;
517  Xyce::dout() << section_divider << std::endl;
518  Xyce::dout() << "Instance::loadDAEdFdxExtractedConductance" << std::endl;
519  }
520 
521  int iRow, iCol;
522  int colsGID[10];
523  double valsGID[10];
524  int i;
525  for (i=0;i<10;++i)
526  {
527  colsGID[i] = -1;
528  valsGID[i] = 0.0;
529  }
530 
531  // first put 1's on the diagonals of all the mesh-rows:
532  for (i=0;i<numMeshPoints;++i)
533  {
534 
535 #ifdef Xyce_NEW_BC
536  if (boundarySten[i]) continue;
537 #endif // Xyce_NEW_BC
538 
539  valsGID[0] = 1.0;
540 
541  iRow = Vrowarray[i];
542  if (iRow != -1)
543  {
544  colsGID[0] = iRow;
545  bs1 = dFdx.putRow(iRow,1, valsGID, colsGID);
546  bsuccess = bsuccess && bs1;
547  }
548 
549  iRow = Nrowarray[i];
550  if (iRow != -1)
551  {
552  colsGID[0] = iRow;
553  bs1 = dFdx.putRow(iRow,1, valsGID, colsGID);
554  bsuccess = bsuccess && bs1;
555  }
556 
557  iRow = Prowarray[i];
558  if (iRow != -1)
559  {
560  colsGID[0] = iRow;
561  bs1 = dFdx.putRow(iRow,1, valsGID, colsGID);
562  bsuccess = bsuccess && bs1;
563  }
564  }
565 
566  // now load the equivalent conductances.
567  for (iRow=0; iRow < numElectrodes ; ++iRow)
568  {
569  int iRowGID = dIVec[iRow].gid;
570 
571  if (iRowGID == -1) continue;
572 
573  int count = 0;
574 
575  for (iCol=0; iCol < numElectrodes ; ++iCol)
576  {
577  if (dIVec[iCol].gid == -1) continue;
578 
579  colsGID[count] = dIVec[iCol].gid;
580  valsGID[count] = condVec[iRow][iCol];
581  ++count;
582  }
583 
584  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
585  {
586  Xyce::dout() << "\niRowGID = " << iRowGID;
587  Xyce::dout() << "\tcount = " << count << std::endl;
588  for (int itmp=0;itmp<count;++itmp)
589  {
590  Xyce::dout() << " colsGID["<<itmp<<"] = " << colsGID[itmp];
591  Xyce::dout() << " valsGID["<<itmp<<"] = " << valsGID[itmp] << std::endl;
592  }
593  }
594 
595  bs1 = dFdx.sumIntoRow (iRowGID, count, valsGID, colsGID);
596  bsuccess = bsuccess && bs1;
597  }
598 
599  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
600  {
601  int iE1, iE2;
602  char tmpString[128]; for (int i=0;i<128;++i) tmpString[i] = 0;
603 
604  Xyce::dout() << std::endl;
605  sprintf(tmpString,"ConArray:\t ");
606  Xyce::dout() << std::string(tmpString);
607  for (iE2 = 0; iE2 < numElectrodes; ++ iE2)
608  {
609  sprintf(tmpString,"\t%14s",dIVec[iE2].eName.c_str());
610  Xyce::dout() << std::string(tmpString);
611  }
612  Xyce::dout() << std::endl;
613 
614  for (iE1 = 0; iE1 < numElectrodes; ++iE1)
615  {
616  sprintf(tmpString,"ConArray:\t%14s",dIVec[iE1].eName.c_str());
617  Xyce::dout() << std::string(tmpString);
618  for (iE2 = 0; iE2 < numElectrodes; ++ iE2)
619  {
620  sprintf(tmpString,"\t%14.4e",condVec[iE1][iE2]); Xyce::dout() << std::string(tmpString);
621  }
622  Xyce::dout() << std::endl;
623  }
624  Xyce::dout() << std::endl;
625  }
626 
627  // now load the equivalent conductances.
628 
629  return bsuccess;
630 }
631 
632 //-----------------------------------------------------------------------------
633 // Function : Instance::loadDAEdQdx
634 // Purpose :
635 // Special Notes :
636 // Scope : private
637 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
638 // Creation Date : 6/21/05
639 //-----------------------------------------------------------------------------
641 {
642  bool bsuccess;
643 
644  if ((getSolverState().dcopFlag) && getSolverState().doubleDCOPStep == 0)
645  {
646  bsuccess = true; // no-op
647  }
648  else
649  {
650  if (getSolverState().twoLevelNewtonCouplingMode==Nonlinear::INNER_PROBLEM ||
651  getSolverState().twoLevelNewtonCouplingMode==Nonlinear::FULL_PROBLEM)
652  {
653  bsuccess = loadDAEdQdxDDFormulation ();
654  }
655  else if (getSolverState().twoLevelNewtonCouplingMode==Nonlinear::OUTER_PROBLEM)
656  {
657  bsuccess = loadDAEdQdxExtractedConductance ();
658  }
659  else
660  {
661  Report::DevelFatal().in("Instance::loadDAEdQdx") << "Invalid coupling Mode" << numElectrodes;
662  }
663  }
664 
665  return bsuccess;
666 }
667 
668 //-----------------------------------------------------------------------------
669 // Function : Instance::loadDAEdQdxDDFormulation
670 // Purpose :
671 // Special Notes :
672 // Scope : private
673 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
674 // Creation Date : 6/21/05
675 //-----------------------------------------------------------------------------
677 {
678  bool bsuccess = true;
679  bool bs1 = true;
680  int i,j,count;
681  int Nrow, Prow;
682 
683  int numCol = cols.size();
684  if (vals.size () < cols.size()) numCol = vals.size();
685 
686  Linear::Matrix & QMatrix = (*extData.dQdxMatrixPtr);
687 
688  // load the rows associated with the PDE mesh:
689  if( useMatrixGIDFlag )
690  {
691  for (i=0;i<numMeshPoints;++i)
692  {
693  if (boundarySten[i]) continue;
694 
695  Nrow = Nrowarray[i];
696  Prow = Prowarray[i];
697 
698  // electron continuity row:
699  for (j=0;j<numCol;++j) { cols[j] = -1; vals[j] = 0.0; }
700  count = 0;
701 
702  // center point
703  vals[count] = -scalingVars.t0;
704  cols[count] = Ncolarray[i][0];
705  ++count;
706 
707  if (Nrow != -1 && count > 0)
708  {
709  bs1 = QMatrix.sumIntoRow (Nrow,count,&vals[0],&cols[0]);
710  bsuccess = bsuccess && bs1;
711  }
712  else
713  {
714  Report::DevelFatal() << "OOOPS 1!";
715  }
716 
717  // hole continuity row:
718  for (j=0;j<numCol;++j) { cols[j] = -1; vals[j] = 0.0; }
719  count = 0;
720 
721  // center point
722  vals[count] = -scalingVars.t0;
723  cols[count] = Pcolarray[i][0];
724  ++count;
725 
726  if (Prow != -1 && count > 0)
727  {
728  bs1 = QMatrix.sumIntoRow (Prow,count,&vals[0],&cols[0]);
729  bsuccess = bsuccess && bs1;
730  }
731  else
732  {
733  Report::DevelFatal() << "OOOPS 2!";
734  }
735 
736  } // mesh loop.
737  }
738  else // direct matrix access:
739  {
740  for (i=0;i<numMeshPoints;++i)
741  {
742  if (boundarySten[i]) continue;
743 
744  Nrow = li_Nrowarray[i];
745  Prow = li_Prowarray[i];
746 
747  std::vector<int> & Noff = li_NoffsetArray[i];
748  std::vector<int> & Poff = li_PoffsetArray[i];
749 
750  QMatrix[Nrow][Noff[0]] += -scalingVars.t0;
751  QMatrix[Prow][Poff[0]] += -scalingVars.t0;
752 
753  } // mesh loop.
754  }
755 
756  return bsuccess;
757 }
758 
759 } // namespace TwoDPDE
760 } // namespace Device
761 } // namespace Xyce
762 
std::vector< double > & vals
Linear::Vector * daeQVectorPtr
Pure virtual class to augment a linear system.
std::vector< int > Vrowarray
Definition: N_DEV_2DPDE.h:457
bool loadMatKCLDDForm(Linear::Matrix *matPtr)
std::vector< int > Nrowarray
Definition: N_DEV_2DPDE.h:461
std::vector< int > boundarySten
Definition: N_DEV_2DPDE.h:441
std::vector< std::vector< int > > li_PoffsetArray
Definition: N_DEV_2DPDE.h:480
std::vector< std::vector< int > > Ncolarray
Definition: N_DEV_2DPDE.h:462
const DeviceOptions & getDeviceOptions() const
std::vector< int > li_Nrowarray
Definition: N_DEV_2DPDE.h:475
Linear::Vector * JdxpVectorPtr
std::vector< double > nnVec
Definition: N_DEV_2DPDE.h:391
std::vector< std::vector< double > > condVec
Definition: N_DEV_2DPDE.h:529
bool loadVecNLPoisson(double scalar, Linear::Vector *vecPtr)
Linear::Matrix * dFdxMatrixPtr
std::vector< DeviceInterfaceNode > dIVec
Definition: N_DEV_2DPDE.h:291
bool loadVecDDForm(double scalar, double dndtScalar, Linear::Vector *vecPtr)
const SolverState & getSolverState() const
std::vector< std::vector< int > > Pcolarray
Definition: N_DEV_2DPDE.h:466
std::vector< double > npVec
Definition: N_DEV_2DPDE.h:392
Linear::Vector * daeFVectorPtr
bool loadMatNLPoisson(Linear::Matrix *matPtr)
bool loadMatCktTrivial(Linear::Matrix *matPtr)
std::vector< int > li_Prowarray
Definition: N_DEV_2DPDE.h:476
std::vector< int > Prowarray
Definition: N_DEV_2DPDE.h:465
bool loadMatDDForm(double dndtScalar, Linear::Matrix *matPtr)
Linear::Matrix * dQdxMatrixPtr
std::vector< std::vector< int > > li_NoffsetArray
Definition: N_DEV_2DPDE.h:479