1 #ifndef THERMOSTAT_H
2 #define THERMOSTAT_H
3 
4 #include "AtomicRegulator.h"
5 #include "PerAtomQuantityLibrary.h"
6 #include <map>
7 #include <set>
8 #include <string>
9 
10 namespace ATC {
11 
12   static const int myLambdaMaxIterations = 50;
13 
14   // forward declarations
15   class ThermalTimeIntegrator;
16   class AtfShapeFunctionRestriction;
17   class FundamentalAtomQuantity;
18   class PrescribedDataManager;
19 
20   /**
21    *  @class  Thermostat
22    *  @brief  Manager class for atom-continuum control of thermal energy
23    */
24   class Thermostat : public AtomicRegulator {
25 
26   public:
27 
28     // constructor
29     Thermostat(ATC_Coupling * atc,
30                const std::string & regulatorPrefix = "");
31 
32     // destructor
~Thermostat()33     virtual ~Thermostat(){};
34 
35     /** parser/modifier */
36     virtual bool modify(int narg, char **arg);
37 
38     /** instantiate up the desired method(s) */
39     virtual void construct_methods();
40 
41     // data access, intended for method objects
42     /** reset the nodal power to a prescribed value */
43     virtual void reset_lambda_contribution(const DENS_MAT & target);
44 
45     /** return value for the correction maximum number of iterations */
lambda_max_iterations()46     int lambda_max_iterations() {return lambdaMaxIterations_;};
47 
48   protected:
49 
50     // data regarding fixed nodes and applied fluxes
51     /** set of all fixed nodes */
52     std::set<int> fixedNodes_;
53     /** set of all nodes which have a flux applied */
54     std::set<int> fluxNodes_;
55 
56     /** maximum number of iterations used in iterative solve for lambda */
57     int lambdaMaxIterations_;
58 
59   private:
60 
61     // DO NOT define this
62     Thermostat();
63 
64   };
65 
66   /**
67    *  @class  ThermostatShapeFunction
68    *  @brief  Class for thermostat algorithms using the shape function matrices
69    *          (thermostats have general for of N^T w N lambda = rhs)
70    */
71 
72   class ThermostatShapeFunction : public RegulatorShapeFunction {
73 
74 
75   public:
76 
77     ThermostatShapeFunction(AtomicRegulator * thermostat,
78                             const std::string & regulatorPrefix = "");
79 
~ThermostatShapeFunction()80     virtual ~ThermostatShapeFunction() {};
81 
82     /** instantiate all needed data */
83     virtual void construct_transfers();
84 
85   protected:
86 
87     // methods
88     /** set weighting factor for in matrix Nhat^T * weights * Nhat */
89     virtual void set_weights();
90 
91     // member data
92 
93     /** MD mass matrix */
94     DIAG_MAN & mdMassMatrix_;
95 
96     /** pointer to atom velocities */
97     FundamentalAtomQuantity * atomVelocities_;
98 
99     /** workspace variables */
100     DENS_VEC _weightVector_, _maskedWeightVector_;
101 
102   private:
103 
104     // DO NOT define this
105     ThermostatShapeFunction();
106 
107   };
108 
109   /**
110    *  @class  ThermostatRescale
111    *  @brief  Enforces constraint on atomic kinetic energy based on FE temperature
112    */
113 
114   class ThermostatRescale : public ThermostatShapeFunction {
115 
116   public:
117 
118     friend class KinetoThermostatRescale; // since this is sometimes used as a set of member functions for friend
119 
120     ThermostatRescale(AtomicRegulator * thermostat);
121 
~ThermostatRescale()122     virtual ~ThermostatRescale() {};
123 
124     /** instantiate all needed data */
125     virtual void construct_transfers();
126 
127     /** applies thermostat to atoms in the post-corrector phase */
128     virtual void apply_post_corrector(double dt);
129 
130     /** compute boundary flux, requires thermostat input since it is part of the coupling scheme */
compute_boundary_flux(FIELDS &)131     virtual void compute_boundary_flux(FIELDS & /* fields */)
132       {boundaryFlux_[TEMPERATURE] = 0.;};
133 
134     /** get data for output */
135     virtual void output(OUTPUT_LIST & outputData);
136 
137   protected:
138 
139     /** set weighting factor for in matrix Nhat^T * weights * Nhat */
140     virtual void set_weights();
141 
142     /** sets up and solves thermostat equations */
143     virtual void compute_thermostat(double dt);
144 
145     /** apply solution to atomic quantities */
146     void apply_to_atoms(PerAtomQuantity<double> * atomVelocities);
147 
148     /** construct the RHS vector */
149     virtual void set_rhs(DENS_MAT & rhs);
150 
151     /** FE temperature field */
152     DENS_MAN & nodalTemperature_;
153 
154     /** construction for prolongation of lambda to atoms */
155     AtomicVelocityRescaleFactor * atomVelocityRescalings_;
156 
157     /** workspace variables */
158     DENS_MAT _rhs_;
159 
160   private:
161 
162     // DO NOT define this
163     ThermostatRescale();
164 
165   };
166 
167   /**
168    *  @class  ThermostatRescaleMixedKePe
169    *  @brief  Enforces constraint on atomic kinetic energy based on FE temperature
170    *          when the temperature is a mix of the KE and PE
171    */
172 
173   class ThermostatRescaleMixedKePe : public ThermostatRescale {
174 
175   public:
176 
177     ThermostatRescaleMixedKePe(AtomicRegulator * thermostat);
178 
~ThermostatRescaleMixedKePe()179     virtual ~ThermostatRescaleMixedKePe() {};
180 
181     /** instantiate all needed data */
182     virtual void construct_transfers();
183 
184     /** pre-run initialization of method data */
185     virtual void initialize();
186 
187   protected:
188 
189     /** set weighting factor for in matrix Nhat^T * weights * Nhat */
190     virtual void set_weights();
191 
192     /** construct the RHS vector */
193     virtual void set_rhs(DENS_MAT & rhs);
194 
195     /** nodal fluctuating potential energy */
196     DENS_MAN * nodalAtomicFluctuatingPotentialEnergy_;
197 
198     /** fraction of temperature from KE */
199     double keMultiplier_;
200 
201     /** fraction of temperature from PE */
202     double peMultiplier_;
203 
204   private:
205 
206     // DO NOT define this
207     ThermostatRescaleMixedKePe();
208 
209   };
210 
211     /**
212    *  @class  ThermostatFsSolver
213    *  @brief  Class for solving the linear system for lambda
214    *          (thermostats have general for of N^T w N lambda = rhs)
215    */
216 
217   class ThermostatFsSolver : public RegulatorShapeFunction {
218 
219 
220   public:
221 
222     ThermostatFsSolver(AtomicRegulator * thermostat,
223                        int lambdaMaxIterations,
224                        const std::string & regulatorPrefix = "");
225 
~ThermostatFsSolver()226     virtual ~ThermostatFsSolver() {};
227 
228     /** pre-run initialization of method data */
229     virtual void initialize();
230 
231     /* sets up and solves the linear system for lambda */
232     virtual void compute_lambda(const DENS_MAT & rhs,
233                                 bool iterateSolution = true);
234 
235     /* scales lambda */
scale_lambda(double factor)236     virtual void scale_lambda(double factor) {*lambda_ *= factor;};
237 
238     /** change the time step factor */
set_timestep_factor(double dtFactor)239     virtual void set_timestep_factor(double dtFactor) {dtFactor_ = dtFactor;};
240 
241   protected:
242 
243     // methods
244     /** solves the non-linear equation for lambda iteratively */
245     void iterate_lambda(const MATRIX & rhs);
246 
247     /** set weighting factor for in matrix Nhat^T * weights * Nhat */
248     virtual void set_weights();
249 
250     // data
251     /** mapping from all to regulated nodes */
252     DENS_MAT rhsMap_;
253 
254     /** maximum number of iterations used in iterative solve for lambda */
255     int lambdaMaxIterations_;
256 
257     /** pointer to the values of lambda interpolated to atoms */
258     DENS_MAN * rhsLambdaSquared_;
259 
260     /** fraction of timestep over which constraint is exactly enforced */
261     double dtFactor_;
262 
263     // workspace
264     DENS_MAT _lambdaOld_; // lambda from previous iteration
265     DENS_MAT _rhsOverlap_; // normal RHS vector mapped to overlap nodes
266     DENS_VEC _rhsTotal_; // normal + 2nd order RHS for the iteration loop
267     DENS_VEC _weightVector_, _maskedWeightVector_;
268 
269   private:
270 
271     // DO NOT define this
272     ThermostatFsSolver();
273 
274   };
275 
276   /**
277    *  @class  ThermostatGlcFs
278    *  @brief  Class for thermostat algorithms which perform the time-integration component of the fractional step method
279    */
280 
281   class ThermostatGlcFs : public RegulatorMethod {
282 
283   public:
284 
285     ThermostatGlcFs(AtomicRegulator * thermostat,
286                     int lambdaMaxIterations,
287                     const std::string & regulatorPrefix = "");
288 
~ThermostatGlcFs()289     virtual ~ThermostatGlcFs() {};
290 
291     /** instantiate all needed data */
292     virtual void construct_transfers();
293 
294     /** pre-run initialization of method data */
295     virtual void initialize();
296 
297     /** applies thermostat to atoms in the predictor phase */
298     virtual void apply_pre_predictor(double dt);
299 
300     /** applies thermostat to atoms in the pre-corrector phase */
301     virtual void apply_pre_corrector(double dt);
302 
303     /** applies thermostat to atoms in the post-corrector phase */
304     virtual void apply_post_corrector(double dt);
305 
306     /** compute boundary flux, requires regulator input since it is part of the coupling scheme */
307     virtual void compute_boundary_flux(FIELDS & fields);
308 
309     /** get data for output */
310     virtual void output(OUTPUT_LIST & outputData);
311 
312     /* flag for performing the full lambda prediction calculation */
313     bool full_prediction();
314 
315     /** set up atom to material identification */
316     virtual void reset_atom_materials(const Array<int> & elementToMaterialMap,
317                                       const MatrixDependencyManager<DenseMatrix, int> * atomElement);
318 
319   protected:
320 
321     // methods
322     /** sets up appropriate rhs for thermostat equations */
323     virtual void set_thermostat_rhs(DENS_MAT & rhs,
324                                     double dt) = 0;
325 
326     /** apply forces to atoms */
327     virtual void apply_to_atoms(PerAtomQuantity<double> * atomicVelocity,
328                                 const DENS_MAN * nodalAtomicEnergy,
329                                 const DENS_MAT & lambdaForce,
330                                 DENS_MAT & nodalAtomicLambdaPower,
331                                 double dt);
332 
333     /** add contributions from thermostat to FE energy */
334     virtual void add_to_energy(const DENS_MAT & nodalLambdaPower,
335                                DENS_MAT & deltaEnergy,
336                                double dt) = 0;
337 
338     /* sets up and solves the linear system for lambda */
339     virtual void compute_lambda(double dt,
340                                 bool iterateSolution = true);
341 
342     // member data
343     /** solver for lambda linear system */
344     ThermostatFsSolver * lambdaSolver_;
345 
346 
347     /** MD mass matrix */
348     DIAG_MAN & mdMassMatrix_;
349 
350     /** pointer to atom velocities */
351     FundamentalAtomQuantity * atomVelocities_;
352 
353     /** reference to AtC FE temperature */
354     DENS_MAN & temperature_;
355 
356     /** pointer to a time filtering object */
357     TimeFilter * timeFilter_;
358 
359     /** power induced by lambda */
360     DENS_MAN * nodalAtomicLambdaPower_;
361 
362     /** filtered lambda power */
363     DENS_MAN * lambdaPowerFiltered_;
364 
365     /** lambda at atomic locations */
366     PerAtomQuantity<double> * atomLambdas_;
367 
368     /** atomic force induced by lambda */
369     AtomicThermostatForce * atomThermostatForces_;
370 
371     /** pointer to atom masses */
372     FundamentalAtomQuantity * atomMasses_;
373 
374     /** hack to determine if first timestep has been passed */
375     bool isFirstTimestep_;
376 
377     /** nodal atomic energy */
378     DENS_MAN * nodalAtomicEnergy_;
379 
380     /** local version of velocity used as predicted final veloctiy */
381     PerAtomQuantity<double> * atomPredictedVelocities_;
382 
383     /** predicted nodal atomic energy */
384     AtfShapeFunctionRestriction * nodalAtomicPredictedEnergy_;
385 
386     /** pointer for force applied in first time step */
387     DENS_MAN * firstHalfAtomForces_;
388 
389     /** FE temperature change from thermostat during predictor phase in second half of timestep */
390     DENS_MAT deltaEnergy1_;
391 
392     /** FE temperature change from thermostat during corrector phase in second half of timestep */
393     DENS_MAT deltaEnergy2_;
394 
395     /** right-hand side data for thermostat equation */
396     DENS_MAT rhs_;
397 
398     // workspace
399     DENS_MAT _lambdaPowerOutput_; // power applied by lambda in output format
400     DENS_MAT _velocityDelta_; // change in velocity when lambda force is applied
401     DENS_VEC _lambdaOverlap_; // lambda in MD overlapping FE nodes
402 
403   private:
404 
405     // DO NOT define this
406     ThermostatGlcFs();
407 
408   };
409 
410   /**
411    *  @class  ThermostatSolverFlux
412    *  @brief  Class enforces GLC on atomic forces based on FE power when using fractional step time integration
413    */
414 
415   class ThermostatSolverFlux : public ThermostatFsSolver {
416 
417   public:
418 
419     ThermostatSolverFlux(AtomicRegulator * thermostat,
420                          int lambdaMaxIterations,
421                          const std::string & regulatorPrefix = "");
422 
~ThermostatSolverFlux()423     virtual ~ThermostatSolverFlux() {};
424 
425     /** instantiate all needed data */
426     virtual void construct_transfers();
427 
428   protected:
429 
430     // methods
431     /** sets up the transfer which is the set of nodes being regulated */
432     virtual void construct_regulated_nodes();
433 
434   private:
435 
436     // DO NOT define this
437     ThermostatSolverFlux();
438 
439   };
440 
441   /**
442    *  @class  ThermostatIntegratorFlux
443    *  @brief  Class integrates GLC on atomic forces based on FE power when using fractional step time integration
444    */
445 
446   class ThermostatIntegratorFlux : public ThermostatGlcFs {
447 
448   public:
449 
450     ThermostatIntegratorFlux(AtomicRegulator * thermostat,
451                              int lambdaMaxIterations,
452                              const std::string & regulatorPrefix = "");
453 
~ThermostatIntegratorFlux()454     virtual ~ThermostatIntegratorFlux() {};
455 
456     /** pre-run initialization of method data */
457     virtual void initialize();
458 
459   protected:
460 
461     /** sets up appropriate rhs for thermostat equations */
462     virtual void set_thermostat_rhs(DENS_MAT & rhs,
463                                     double dt);
464 
465     /** add contributions from thermostat to FE energy */
466     virtual void add_to_energy(const DENS_MAT & nodalLambdaPower,
467                                DENS_MAT & deltaEnergy,
468                                double dt);
469 
470     // data
471     /** reference to ATC sources coming from prescribed data, AtC coupling, and extrinsic coupling */
472     DENS_MAN & heatSource_;
473 
474   private:
475 
476     // DO NOT define this
477     ThermostatIntegratorFlux();
478 
479   };
480 
481   /**
482    *  @class  ThermostatSolverFixed
483    *  @brief  Class enforces GLC on atomic forces based on FE power when using fractional step time integration
484    */
485 
486   class ThermostatSolverFixed : public ThermostatFsSolver {
487 
488   public:
489 
490     ThermostatSolverFixed(AtomicRegulator * thermostat,
491                           int lambdaMaxIterations,
492                           const std::string & regulatorPrefix = "");
493 
~ThermostatSolverFixed()494     virtual ~ThermostatSolverFixed() {};
495 
496     /** instantiate all needed data */
497     virtual void construct_transfers();
498 
499   protected:
500 
501     // methods
502     /** sets up the transfer which is the set of nodes being regulated */
503     virtual void construct_regulated_nodes();
504 
505    private:
506 
507     // DO NOT define this
508     ThermostatSolverFixed();
509 
510   };
511 
512   /**
513    *  @class  ThermostatIntegratorFixed
514    *  @brief  Class integrates GLC on atomic forces based on FE power when using fractional step time integration
515    */
516 
517   class ThermostatIntegratorFixed : public ThermostatGlcFs {
518 
519   public:
520 
521     ThermostatIntegratorFixed(AtomicRegulator * thermostat,
522                               int lambdaMaxIterations,
523                               const std::string & regulatorPrefix = "");
524 
~ThermostatIntegratorFixed()525     virtual ~ThermostatIntegratorFixed() {};
526 
527     /** instantiate all needed data */
528     virtual void construct_transfers();
529 
530     /** pre-run initialization of method data */
531     virtual void initialize();
532 
533     /** applies thermostat to atoms in the predictor phase */
534     virtual void apply_pre_predictor(double dt);
535 
536     /** applies thermostat to atoms in the pre-corrector phase */
537     virtual void apply_pre_corrector(double dt);
538 
539     /** applies thermostat to atoms in the post-corrector phase */
540     virtual void apply_post_corrector(double dt);
541 
542     /** compute boundary flux, requires thermostat input since it is part of the coupling scheme */
compute_boundary_flux(FIELDS &)543     virtual void compute_boundary_flux(FIELDS & /* fields */)
544       {boundaryFlux_[TEMPERATURE] = 0.;};
545 
546     /** determine if local shape function matrices are needed */
use_local_shape_functions()547     virtual bool use_local_shape_functions() const {return atomicRegulator_->use_localized_lambda();};
548 
549   protected:
550 
551     // methods
552     /** initialize data for tracking the change in nodal atomic temperature */
553     virtual void initialize_delta_nodal_atomic_energy(double dt);
554 
555     /** compute the change in nodal atomic temperature */
556     virtual void compute_delta_nodal_atomic_energy(double dt);
557 
558     /** sets up appropriate rhs for thermostat equations */
559     virtual void set_thermostat_rhs(DENS_MAT & rhs,
560                                     double dt);
561 
562     /** add contributions from thermostat to FE energy */
563     virtual void add_to_energy(const DENS_MAT & nodalLambdaPower,
564                                DENS_MAT & deltaEnergy,
565                                double dt);
566 
567     /* sets up and solves the linear system for lambda */
568     virtual void compute_lambda(double dt,
569                                 bool iterateSolution = true);
570 
571     /** flag for halving the applied force to mitigate numerical errors */
572     bool halve_force();
573 
574     // data
575     /** change in FE energy over a timestep */
576     DENS_MAT deltaFeEnergy_;
577 
578     /** initial FE energy used to compute change */
579     DENS_MAT initialFeEnergy_;
580 
581     /** change in restricted atomic FE energy over a timestep */
582     DENS_MAT deltaNodalAtomicEnergy_;
583 
584     /** initial restricted atomic FE energy used to compute change */
585     DENS_MAT initialNodalAtomicEnergy_;
586 
587     /** filtered nodal atomic energy */
588     DENS_MAN nodalAtomicEnergyFiltered_;
589 
590     /** forces depending on predicted velocities for correct updating with fixed nodes */
591     AtomicThermostatForce * atomThermostatForcesPredVel_;
592 
593     /** coefficient to account for effect of time filtering on rhs terms */
594     double filterCoefficient_;
595 
596     /** kinetic energy multiplier in total energy (used for temperature expression) */
597     double keMultiplier_;
598 
599     // workspace
600     DENS_MAT _tempNodalAtomicEnergyFiltered_; // stores filtered energy change in atoms for persistence during predictor
601 
602   private:
603 
604     // DO NOT define this
605     ThermostatIntegratorFixed();
606 
607   };
608 
609   /**
610    *  @class  ThermostatIntegratorFluxFiltered
611    *  @brief  Class integrates GLC on atomic forces based on FE power when using fractional step time integration
612    *          in conjunction with time filtering
613    */
614 
615   class ThermostatIntegratorFluxFiltered : public ThermostatIntegratorFlux {
616 
617   public:
618 
619     ThermostatIntegratorFluxFiltered(AtomicRegulator * thermostat,
620                                      int lambdaMaxIterations,
621                                      const std::string & regulatorPrefix = "");
622 
~ThermostatIntegratorFluxFiltered()623     virtual ~ThermostatIntegratorFluxFiltered() {};
624 
625     /** pre-run initialization of method data */
626     virtual void initialize();
627 
628     /** applies thermostat to atoms in the post-corrector phase */
629     virtual void apply_post_corrector(double dt);
630 
631     /** get data for output */
632     virtual void output(OUTPUT_LIST & outputData);
633 
634   protected:
635 
636     /** sets up appropriate rhs for thermostat equations */
637     virtual void set_thermostat_rhs(DENS_MAT & rhs,
638                                     double dt);
639 
640     /** add contributions from thermostat to FE energy */
641     virtual void add_to_energy(const DENS_MAT & nodalLambdaPower,
642                                DENS_MAT & deltaEnergy,
643                                double dt);
644 
645     // data
646     /** heat source time history required to get instantaneous heat sources */
647     DENS_MAT heatSourceOld_;
648     DENS_MAT instantHeatSource_;
649     DENS_MAT timeStepSource_;
650 
651   private:
652 
653     // DO NOT define this
654     ThermostatIntegratorFluxFiltered();
655 
656   };
657 
658   /**
659    *  @class  ThermostatIntegratorFixedFiltered
660    *  @brief  Class for thermostatting using the temperature matching constraint and is compatible with
661  the fractional step time-integration with time filtering
662    */
663 
664   class ThermostatIntegratorFixedFiltered : public ThermostatIntegratorFixed {
665 
666   public:
667 
668     ThermostatIntegratorFixedFiltered(AtomicRegulator * thermostat,
669                                       int lambdaMaxIterations,
670                                       const std::string & regulatorPrefix = "");
671 
~ThermostatIntegratorFixedFiltered()672     virtual ~ThermostatIntegratorFixedFiltered() {};
673 
674     /** get data for output */
675     virtual void output(OUTPUT_LIST & outputData);
676 
677   protected:
678 
679     // methods
680     /** initialize data for tracking the change in nodal atomic temperature */
681     virtual void initialize_delta_nodal_atomic_energy(double dt);
682 
683     /** compute the change in nodal atomic temperature */
684     virtual void compute_delta_nodal_atomic_energy(double dt);
685 
686     /** sets up appropriate rhs for thermostat equations */
687     virtual void set_thermostat_rhs(DENS_MAT & rhs,
688                                     double dt);
689 
690     /** add contributions from thermostat to temperature for uncoupled nodes */
691     virtual void add_to_energy(const DENS_MAT & nodalLambdaPower,
692                                DENS_MAT & deltaEnergy,
693                                double dt);
694 
695   private:
696 
697     // DO NOT define this
698     ThermostatIntegratorFixedFiltered();
699 
700   };
701 
702   /**
703    *  @class  ThermostatFluxFixed
704    *  @brief  Class for thermostatting using the temperature matching constraint one one set of nodes and the flux matching constraint on another
705    */
706 
707   class ThermostatFluxFixed : public RegulatorMethod {
708 
709   public:
710 
711     ThermostatFluxFixed(AtomicRegulator * thermostat,
712                         int lambdaMaxIterations,
713                         bool constructThermostats = true);
714 
715     virtual ~ThermostatFluxFixed();
716 
717     /** instantiate all needed data */
718     virtual void construct_transfers();
719 
720     /** pre-run initialization of method data */
721     virtual void initialize();
722 
723     /** applies thermostat to atoms in the predictor phase */
724     virtual void apply_pre_predictor(double dt);
725 
726     /** applies thermostat to atoms in the pre-corrector phase */
727     virtual void apply_pre_corrector(double dt);
728 
729     /** applies thermostat to atoms in the post-corrector phase */
730     virtual void apply_post_corrector(double dt);
731 
732     /** get data for output */
733     virtual void output(OUTPUT_LIST & outputData);
734 
735     /** compute boundary flux, requires thermostat input since it is part of the coupling scheme */
compute_boundary_flux(FIELDS & fields)736     virtual void compute_boundary_flux(FIELDS & fields)
737       {thermostatBcs_->compute_boundary_flux(fields);};
738 
739   protected:
740 
741     // data
742     /** thermostat for imposing the fluxes */
743     ThermostatIntegratorFlux * thermostatFlux_;
744 
745     /** thermostat for imposing fixed nodes */
746     ThermostatIntegratorFixed * thermostatFixed_;
747 
748     /** pointer to whichever thermostat should compute the flux, based on coupling method */
749     ThermostatGlcFs * thermostatBcs_;
750 
751   private:
752 
753     // DO NOT define this
754     ThermostatFluxFixed();
755   };
756 
757   /**
758    *  @class  ThermostatFluxFixedFiltered
759    *  @brief  Class for thermostatting using the temperature matching constraint one one set of nodes and the flux matching constraint on another with time filtering
760    */
761 
762   class ThermostatFluxFixedFiltered : public ThermostatFluxFixed {
763 
764   public:
765 
766     ThermostatFluxFixedFiltered(AtomicRegulator * thermostat,
767                                 int lambdaMaxIterations);
768 
~ThermostatFluxFixedFiltered()769     virtual ~ThermostatFluxFixedFiltered(){};
770 
771   private:
772 
773     // DO NOT define this
774     ThermostatFluxFixedFiltered();
775 
776   };
777 
778   /**
779    *  @class  ThermostatGlc
780    *  @brief  Class for thermostat algorithms based on Gaussian least constraints (GLC)
781    */
782 
783   class ThermostatGlc : public ThermostatShapeFunction {
784 
785   public:
786 
787     ThermostatGlc(AtomicRegulator * thermostat);
788 
~ThermostatGlc()789     virtual ~ThermostatGlc() {};
790 
791     /** instantiate all needed data */
792     virtual void construct_transfers();
793 
794   protected:
795 
796     // methods
797     /** apply forces to atoms */
798     virtual void apply_to_atoms(PerAtomQuantity<double> * atomicVelocity,
799                                 const DENS_MAT & lambdaForce,
800                                 double dt);
801 
802     // member data
803     /** pointer to a time filtering object */
804     TimeFilter * timeFilter_;
805 
806     /** filtered lambda power */
807     DENS_MAN * lambdaPowerFiltered_;
808 
809     /** atomic force induced by lambda */
810     PerAtomQuantity<double> * atomThermostatForces_;
811 
812     /** pointer to access prescribed data for fixed nodes */
813     PrescribedDataManager * prescribedDataMgr_;
814 
815     /** pointer to atom masses */
816     FundamentalAtomQuantity * atomMasses_;
817 
818     /** workspace variables */
819     DENS_MAT _velocityDelta_;
820 
821   private:
822 
823     // DO NOT define this
824     ThermostatGlc();
825 
826   };
827 
828   /**
829    *  @class  ThermostatPowerVerlet
830    *  @brief  Class for thermostatting using the heat flux matching constraint and is compatible with
831  the Gear time-integration
832    */
833 
834   class ThermostatPowerVerlet : public ThermostatGlc {
835 
836   public:
837 
838     ThermostatPowerVerlet(AtomicRegulator * thermostat);
839 
~ThermostatPowerVerlet()840     virtual ~ThermostatPowerVerlet() {};
841 
842     /** instantiate all needed data */
843     virtual void construct_transfers();
844 
845     /** pre-run initialization of method data */
846     virtual void initialize();
847 
848     /** applies thermostat to atoms in the predictor phase */
849     virtual void apply_pre_predictor(double dt);
850 
851     /** applies thermostat to atoms in the pre-corrector phase */
852     virtual void apply_pre_corrector(double dt);
853 
854     /** get data for output */
855     virtual void output(OUTPUT_LIST & outputData);
856 
857     /** final tasks of a run */
858     virtual void finish();
859 
860     /** determine if local shape function matrices are needed */
use_local_shape_functions()861     virtual bool use_local_shape_functions() const {return (!(atomicRegulator_->use_lumped_lambda_solve()) && atomicRegulator_->use_localized_lambda());};
862 
863   protected:
864 
865     /** nodal temperature rate of change */
866     DENS_MAN & nodalTemperatureRoc_;
867 
868     /** reference to ATC sources coming from prescribed data, AtC coupling, and extrinsic coupling */
869     DENS_MAN & heatSource_;
870 
871     /** pointer to nodal atomic power */
872     DENS_MAN * nodalAtomicPower_;
873 
874     /** power applied to each atom by lambda force */
875     AtfShapeFunctionRestriction * nodalAtomicLambdaPower_;
876 
877     /** workspace variables */
878     DENS_MAT _rhs_;
879 
880     /** sets up and solves thermostat equations */
881     virtual void compute_thermostat(double dt);
882 
883     /** sets up appropriate rhs for thermostat equations */
884     virtual void set_thermostat_rhs(DENS_MAT & rhs_nodes);
885 
886     /** add contributions (if any) to the finite element right-hand side */
887     virtual void add_to_rhs(FIELDS & rhs);
888 
889     // workspace
890     DENS_MAT _nodalAtomicLambdaPowerOut_; // power induced by lambda in output format
891 
892   private:
893 
894     // DO NOT define this
895     ThermostatPowerVerlet();
896 
897   };
898 
899   /**
900    *  @class  ThermostatHooverVerlet
901    *  @brief  Classfor thermostatting using the temperature matching constraint and is compatible with
902  Gear time-integration
903    */
904 
905   class ThermostatHooverVerlet : public ThermostatPowerVerlet {
906 
907   public:
908 
909     ThermostatHooverVerlet(AtomicRegulator * thermostat);
910 
~ThermostatHooverVerlet()911     virtual ~ThermostatHooverVerlet() {};
912 
913     /** instantiate all needed data */
914     virtual void construct_transfers();
915 
916     /** final tasks of a run */
finish()917     virtual void finish() {};
918 
919     /** compute boundary flux, requires thermostat input since it is part of the coupling scheme */
compute_boundary_flux(FIELDS &)920     virtual void compute_boundary_flux(FIELDS & /* fields */)
921       {boundaryFlux_[TEMPERATURE] = 0.;};
922 
923   protected:
924 
925     /** lambda coupling parameter for hoover thermostat */
926     DENS_MAN * lambdaHoover_;
927 
928     /** workspace variables */
929     DENS_MAT _myNodalLambdaPower_;
930 
931     /** sets up and solves thermostat equations */
932     virtual void compute_thermostat(double dt);
933 
934     /** sets up Hoover component of the thermostat */
935     void set_hoover_rhs(DENS_MAT & rhs);
936 
937     /** add Hoover contributions to lambda power */
938     void add_to_lambda_power(const DENS_MAT & myLambdaForce,
939                              double dt);
940 
941     /** power applied to each atom by hoover lambda force */
942     AtfShapeFunctionRestriction * nodalAtomicHooverLambdaPower_;
943 
944     /** add contributions (if any) to the finite element right-hand side */
945     virtual void add_to_rhs(FIELDS & rhs);
946 
947   private:
948 
949     // DO NOT implement this
950     ThermostatHooverVerlet();
951 
952   };
953 
954   /**
955    *  @class  ThermostatPowerVerletFiltered
956    *  @brief  Class for thermostatting using the heat flux matching constraint and is compatible with
957  Gear time-integration with time filtering
958    */
959 
960   class ThermostatPowerVerletFiltered : public ThermostatPowerVerlet {
961 
962   public:
963 
964     ThermostatPowerVerletFiltered(AtomicRegulator * thermostat);
965 
~ThermostatPowerVerletFiltered()966     virtual ~ThermostatPowerVerletFiltered(){};
967 
968     /** get data for output */
969     virtual void output(OUTPUT_LIST & outputData);
970 
971     /** compute boundary flux, requires thermostat input since it is part of the coupling scheme */
972     virtual void compute_boundary_flux(FIELDS & fields);
973 
974   protected:
975 
976     /** sets up appropriate rhs for thermostat equations */
977     virtual void set_thermostat_rhs(DENS_MAT & rhs_nodes);
978 
979     /** add contributions (if any) to the finite element right-hand side */
980     virtual void add_to_rhs(FIELDS & rhs);
981 
982     /** nodal temperature 2nd rate of change (i.e. second time derivative) */
983     DENS_MAN & nodalTemperature2Roc_;
984 
985     /** reference to ATC rate of change sources coming from prescribed data, AtC coupling, and extrinsic coupling */
986     DENS_MAN heatSourceRoc_;
987 
988     /** references to ATC field rates of changing for inverting the filtered heat sources */
989     FIELDS & fieldsRoc_;
990 
991     /** flux rate of changes for inverting filtered fluxes */
992     FIELDS fluxRoc_;
993 
994     /** time scale for the time filter */
995     double filterScale_;
996 
997   private:
998 
999     // DO NOT define this
1000     ThermostatPowerVerletFiltered();
1001 
1002   };
1003 
1004   /**
1005    *  @class  ThermostatHooverVerletFiltered
1006    *  @brief  Class for thermostatting using the temperature matching constraint and is compatible with
1007  Gear time-integration with time filtering
1008    */
1009 
1010   class ThermostatHooverVerletFiltered : public ThermostatPowerVerletFiltered {
1011 
1012   public:
1013 
1014     ThermostatHooverVerletFiltered(AtomicRegulator * thermostat);
1015 
~ThermostatHooverVerletFiltered()1016     virtual ~ThermostatHooverVerletFiltered() {};
1017 
1018     /** instantiate all needed data */
1019     virtual void construct_transfers();
1020 
1021     /** final tasks of a run */
finish()1022     virtual void finish() {};
1023 
1024     /** compute boundary flux, requires thermostat input since it is part of the coupling scheme */
compute_boundary_flux(FIELDS &)1025     virtual void compute_boundary_flux(FIELDS & /* fields */)
1026       {boundaryFlux_[TEMPERATURE] = 0.;};
1027 
1028   protected:
1029 
1030     /** lambda coupling parameter for hoover thermostat */
1031     DENS_MAN * lambdaHoover_;
1032 
1033     /** workspace variables */
1034     DENS_MAT _myNodalLambdaPower_;
1035 
1036     /** sets up and solves thermostat equations */
1037     virtual void compute_thermostat(double dt);
1038 
1039     /** sets up Hoover component of the thermostat */
1040     void set_hoover_rhs(DENS_MAT & rhs);
1041 
1042     /** add Hoover contributions to lambda power */
1043     void add_to_lambda_power(const DENS_MAT & myLambdaForce,
1044                              double dt);
1045 
1046     /** power applied to each atom by hoover lambda force */
1047     DENS_MAN * nodalAtomicHooverLambdaPower_;
1048 
1049     /** add contributions (if any) to the finite element right-hand side */
1050     virtual void add_to_rhs(FIELDS & rhs);
1051 
1052   private:
1053 
1054     // DO NOT implement this
1055     ThermostatHooverVerletFiltered();
1056 
1057   };
1058 
1059 };
1060 
1061 #endif
1062