1 #ifndef KINETOSTAT_H
2 #define KINETOSTAT_H
3 
4 #include "AtomicRegulator.h"
5 #include "PerAtomQuantityLibrary.h"
6 #include <map>
7 #include <set>
8 #include <utility>
9 #include <string>
10 
11 namespace ATC {
12 
13   // forward declarations
14   class FundamentalAtomQuantity;
15   class AtfShapeFunctionRestriction;
16   template <typename T>
17     class ProtectedAtomQuantity;
18 
19   /**
20    *  @class  Kinetostat
21    *  @brief  Manager class for atom-continuum control of momentum and position
22    */
23 
24   class Kinetostat : public AtomicRegulator {
25 
26   public:
27 
28     // constructor
29     Kinetostat(ATC_Coupling *atc,
30                const std::string & regulatorPrefix = "");
31 
32     // destructor
~Kinetostat()33     virtual ~Kinetostat(){};
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 force to a prescribed value */
43     virtual void reset_lambda_contribution(const DENS_MAT & target);
44 
45   private:
46 
47     // DO NOT define this
48     Kinetostat();
49 
50   };
51 
52   /**
53    *  @class  KinetostatShapeFunction
54    *  @brief  Base class for implementation of kinetostat algorithms based on FE shape functions
55    */
56 
57   class KinetostatShapeFunction : public RegulatorShapeFunction {
58 
59   public:
60 
61     KinetostatShapeFunction(AtomicRegulator *kinetostat,
62                             const std::string & regulatorPrefix = "");
63 
~KinetostatShapeFunction()64     virtual ~KinetostatShapeFunction(){};
65 
66     /** instantiate all needed data */
67     virtual void construct_transfers();
68 
69   protected:
70 
71     // methods
72     /** set weighting factor for in matrix Nhat^T * weights * Nhat */
73     virtual void set_weights();
74 
75     // member data
76     /** MD mass matrix */
77     DIAG_MAN & mdMassMatrix_;
78     /** pointer to a time filtering object */
79     TimeFilter * timeFilter_;
80     /** stress induced by lambda */
81     DENS_MAN * nodalAtomicLambdaForce_;
82     /** filtered lambda force */
83     DENS_MAN * lambdaForceFiltered_;
84     /** atomic force induced by lambda */
85     ProtectedAtomQuantity<double> * atomKinetostatForce_;
86     /** lambda prolonged to the atoms */
87     ProtectedAtomQuantity<double> * atomLambda_;
88 
89     /** pointer to atom velocities */
90     FundamentalAtomQuantity * atomVelocities_;
91     /** pointer to atom velocities */
92     FundamentalAtomQuantity * atomMasses_;
93 
94     // workspace
95     DENS_MAT _nodalAtomicLambdaForceOut_; // matrix for output only
96 
97   private:
98 
99     // DO NOT define this
100     KinetostatShapeFunction();
101 
102   };
103 
104   /**
105    *  @class  GlcKinetostat
106    *  @brief  Base class for implementation of kinetostat algorithms based on Gaussian least constraints (GLC)
107    */
108 
109   class GlcKinetostat : public KinetostatShapeFunction {
110 
111   public:
112 
113     GlcKinetostat(AtomicRegulator *kinetostat);
114 
~GlcKinetostat()115     virtual ~GlcKinetostat(){};
116 
117     /** instantiate all needed data */
118     virtual void construct_transfers();
119 
120     /** pre-run initialization of method data */
121     virtual void initialize();
122 
123   protected:
124 
125     // methods
126     /** apply forces to atoms */
127     virtual void apply_to_atoms(PerAtomQuantity<double> * quantity,
128                                 const DENS_MAT & lambdaAtom,
129                                 double dt=0.);
130 
131     /** apply any required corrections for localized kinetostats */
apply_localization_correction(const DENS_MAT &,DENS_MAT &,double)132     virtual void apply_localization_correction(const DENS_MAT & /* source */,
133                                                DENS_MAT & /* nodalField */,
134                                                double /* weight */){};
apply_localization_correction(const DENS_MAT &,DENS_MAT &)135     virtual void apply_localization_correction(const DENS_MAT & /* source */,
136                                                DENS_MAT & /* nodalField */){};
137 
138     // member data
139     /** nodeset corresponding to Hoover coupling */
140     std::set<std::pair<int,int> > hooverNodes_;
141 
142 
143     /** pointer to atom positions */
144     FundamentalAtomQuantity * atomPositions_;
145 
146   private:
147 
148     // DO NOT define this
149     GlcKinetostat();
150 
151   };
152 
153   /**
154    *  @class  DisplacementGlc
155    *  @brief  Enforces GLC on atomic position based on FE displacement
156    */
157 
158   class DisplacementGlc : public GlcKinetostat {
159 
160   public:
161 
162     DisplacementGlc(AtomicRegulator * kinetostat);
163 
~DisplacementGlc()164     virtual ~DisplacementGlc(){};
165 
166     /** instantiate all needed data */
167     virtual void construct_transfers();
168 
169     /** pre-run initialization of method data */
170     virtual void initialize();
171 
172     /** applies kinetostat to atoms */
173     virtual void apply_post_predictor(double dt);
174 
175     /** get data for output */
176     virtual void output(OUTPUT_LIST & outputData);
177 
178     /** determine if local shape function matrices are needed */
use_local_shape_functions()179     virtual bool use_local_shape_functions() const {return (!atomicRegulator_->use_lumped_lambda_solve()) && atomicRegulator_->use_localized_lambda();};
180 
181   protected:
182 
183     // methods
184     /** set weighting factor for in matrix Nhat^T * weights * Nhat */
185     virtual void set_weights();
186 
187     /** does initial filtering operations before main computation */
188     virtual void apply_pre_filtering(double dt);
189     /** sets up and solves kinetostat equations */
190     virtual void compute_kinetostat(double dt);
191     /** sets up appropriate rhs for kinetostat equations */
192     virtual void set_kinetostat_rhs(DENS_MAT & rhs, double dt);
193     /** computes the nodal FE force applied by the kinetostat */
194     virtual void compute_nodal_lambda_force(double dt);
195     /** apply any required corrections for localized kinetostats */
196     virtual void apply_localization_correction(const DENS_MAT & source,
197                                                DENS_MAT & nodalField,
198                                                double weight = 1.);
199 
200     // data
201     /** restricted atomic displacements at the nodes */
202     DENS_MAN * nodalAtomicMassWeightedDisplacement_;
203     /** clone of FE displacement field */
204     DENS_MAN & nodalDisplacements_;
205 
206   private:
207 
208     // DO NOT define this
209     DisplacementGlc();
210 
211   };
212 
213   /**
214    *  @class  DisplacementGlcFiltered
215    *  @brief  Enforces GLC on time filtered atomic position based on FE displacement
216    */
217 
218   //--------------------------------------------------------
219   //--------------------------------------------------------
220   //  Class DisplacementGlcFiltered
221   //--------------------------------------------------------
222   //--------------------------------------------------------
223 
224   class DisplacementGlcFiltered : public DisplacementGlc {
225 
226   public:
227 
228     DisplacementGlcFiltered(AtomicRegulator * kinetostat);
229 
~DisplacementGlcFiltered()230     virtual ~DisplacementGlcFiltered(){};
231 
232     /** get data for output */
233     virtual void output(OUTPUT_LIST & outputData);
234 
235   protected:
236 
237     // methods
238     /** does initial filtering operations before main computation */
239     virtual void apply_pre_filtering(double dt);
240     /** sets up appropriate rhs for kinetostat equations */
241     virtual void set_kinetostat_rhs(DENS_MAT & rhs, double dt);
242     /** computes the nodal FE force applied by the kinetostat */
243     virtual void compute_nodal_lambda_force(double dt);
244 
245     // data
246     /** clone of FE nodal atomic displacement field */
247     DENS_MAN & nodalAtomicDisplacements_;
248 
249   private:
250 
251     // DO NOT define this
252     DisplacementGlcFiltered();
253 
254   };
255 
256   /**
257    *  @class  VelocityGlc
258    *  @brief  Enforces GLC on atomic velocity based on FE velocity
259    */
260 
261   //--------------------------------------------------------
262   //--------------------------------------------------------
263   //  Class VelocityGlc
264   //--------------------------------------------------------
265   //--------------------------------------------------------
266 
267   class VelocityGlc : public GlcKinetostat {
268 
269   public:
270 
271     VelocityGlc(AtomicRegulator * kinetostat);
272 
~VelocityGlc()273     virtual ~VelocityGlc(){};
274 
275     /** instantiate all needed data */
276     virtual void construct_transfers();
277 
278     /** pre-run initialization of method data */
279     virtual void initialize();
280 
281     /** applies kinetostat to atoms */
282     virtual void apply_mid_predictor(double dt);
283 
284     /** applies kinetostat to atoms */
285     virtual void apply_post_corrector(double dt);
286 
287     /** get data for output */
288     virtual void output(OUTPUT_LIST & outputData);
289 
290     /** determine if local shape function matrices are needed */
use_local_shape_functions()291     virtual bool use_local_shape_functions() const {return (!atomicRegulator_->use_lumped_lambda_solve()) && atomicRegulator_->use_localized_lambda();};
292 
293   protected:
294 
295     // methods
296     /** set weighting factor for in matrix Nhat^T * weights * Nhat */
297     virtual void set_weights();
298 
299     /** does initial filtering operations before main computation */
300     virtual void apply_pre_filtering(double dt);
301     /** sets up and solves kinetostat equations */
302     virtual void compute_kinetostat(double dt);
303     /** applies kinetostat correction to atoms */
304     virtual void apply_kinetostat(double dt);
305     /** sets up appropriate rhs for kinetostat equations */
306     virtual void set_kinetostat_rhs(DENS_MAT & rhs, double dt);
307     /** computes the nodal FE force applied by the kinetostat */
308     virtual void compute_nodal_lambda_force(double dt);
309     /** apply any required corrections for localized kinetostats */
310     virtual void apply_localization_correction(const DENS_MAT & source,
311                                                DENS_MAT & nodalField,
312                                                double weight = 1.);
313 
314     // data
315     /** restricted atomic displacements at the nodes */
316     DENS_MAN * nodalAtomicMomentum_;
317     /** clone of FE velocity field */
318     DENS_MAN & nodalVelocities_;
319 
320   private:
321 
322     // DO NOT define this
323     VelocityGlc();
324 
325   };
326 
327   /**
328    *  @class  VelocityGlcFiltered
329    *  @brief  Enforces GLC on time filtered atomic velocity based on FE velocity
330    */
331 
332   //--------------------------------------------------------
333   //--------------------------------------------------------
334   //  Class VelocityGlcFiltered
335   //--------------------------------------------------------
336   //--------------------------------------------------------
337 
338   class VelocityGlcFiltered : public VelocityGlc {
339 
340   public:
341 
342     VelocityGlcFiltered(AtomicRegulator * kinetostat);
343 
~VelocityGlcFiltered()344     virtual ~VelocityGlcFiltered(){};
345 
346     /** get data for output */
347     virtual void output(OUTPUT_LIST & outputData);
348 
349   protected:
350 
351     // methods
352     /** does initial filtering operations before main computation */
353     virtual void apply_pre_filtering(double dt);
354     /** sets up appropriate rhs for kinetostat equations */
355     virtual void set_kinetostat_rhs(DENS_MAT & rhs, double dt);
356     /** computes the nodal FE force applied by the kinetostat */
357     virtual void compute_nodal_lambda_force(double dt);
358 
359     // data
360     /** clone of FE nodal atomic velocity field */
361     DENS_MAN & nodalAtomicVelocities_;
362 
363   private:
364 
365     // DO NOT define this
366     VelocityGlcFiltered();
367 
368   };
369 
370   /**
371    *  @class  StressFlux
372    *  @brief  Enforces GLC on atomic forces based on FE stresses or accelerations
373    */
374 
375   //--------------------------------------------------------
376   //--------------------------------------------------------
377   //  Class StressFlux
378   //--------------------------------------------------------
379   //--------------------------------------------------------
380 
381   class StressFlux : public GlcKinetostat {
382 
383   public:
384 
385     StressFlux(AtomicRegulator * kinetostat);
386 
387     virtual ~StressFlux();
388 
389     /** instantiate all needed data */
390     virtual void construct_transfers();
391 
392     /** applies kinetostat to atoms in the pre-predictor phase */
393     virtual void apply_pre_predictor(double dt);
394 
395     /** applies kinetostat to atoms in the post-corrector phase */
396     virtual void apply_post_corrector(double dt);
397 
398     /** compute boundary flux, requires thermostat input since it is part of the coupling scheme */
399     virtual void compute_boundary_flux(FIELDS & fields);
400 
401     /** get data for output */
402     virtual void output(OUTPUT_LIST & outputData);
403 
404     /** sets filtered ghost force to prescribed value */
405     void reset_filtered_ghost_force(DENS_MAT & targetForce);
406     /** returns reference to filtered ghost force */
filtered_ghost_force()407     DENS_MAN & filtered_ghost_force() {return nodalGhostForceFiltered_;};
408 
409     /** determine if local shape function matrices are needed */
use_local_shape_functions()410     virtual bool use_local_shape_functions() const {return ((!atomicRegulator_->use_lumped_lambda_solve()) && atomicRegulator_->use_localized_lambda());};
411 
412   protected:
413 
414     // data
415     /** nodal force */
416     DENS_MAN & nodalForce_;
417     /** nodal force due to atoms */
418     DENS_MAN * nodalAtomicForce_;
419     /** nodal ghost force */
420     AtfShapeFunctionRestriction * nodalGhostForce_;
421     /** filtered ghost force */
422     DENS_MAN nodalGhostForceFiltered_;
423     /** reference to ATC sources coming from prescribed data, AtC coupling, and extrinsic coupling */
424     DENS_MAN & momentumSource_;
425 
426     // methods
427     /** does initial filtering operations before main computation */
428     virtual void apply_pre_filtering(double dt);
429     /** sets up and solves kinetostat equations */
430     virtual void compute_kinetostat(double dt);
431     /** sets up appropriate rhs for kinetostat equations */
432     virtual void set_kinetostat_rhs(DENS_MAT & rhs, double dt);
433     /** computes the nodal FE force applied by the kinetostat */
434     virtual void compute_nodal_lambda_force(double dt);
435     /** apply forces to atoms */
436     virtual void apply_to_atoms(PerAtomQuantity<double> * atomVelocities,
437                                 const DENS_MAT & lambdaForce,
438                                 double dt);
439     /** adds in finite element rhs contributions */
440     virtual void add_to_rhs(FIELDS & rhs);
441 
442     // workspace
443     DENS_MAT _deltaVelocity_; // change in velocity during time integration
444   private:
445 
446     // DO NOT define this
447     StressFlux();
448 
449   };
450 
451   /**
452    *  @class  StressFluxGhost
453    *  @brief  Enforces GLC on atomic forces based on FE stresses or accelerations, using
454    *          the ghost forces to prescribe the FE boundary stress
455    */
456 
457   //--------------------------------------------------------
458   //--------------------------------------------------------
459   //  Class StressFluxGhost
460   //--------------------------------------------------------
461   //--------------------------------------------------------
462 
463   class StressFluxGhost : public StressFlux {
464 
465   public:
466 
467     StressFluxGhost(AtomicRegulator * kinetostat);
468 
~StressFluxGhost()469     virtual ~StressFluxGhost() {};
470 
471     /** instantiate all needed data */
472     virtual void construct_transfers();
473 
474     /** compute boundary flux, requires kinetostat input since it is part of the coupling scheme */
475     virtual void compute_boundary_flux(FIELDS & fields);
476 
477   protected:
478 
479     // methods
480     /** sets up appropriate rhs for kinetostat equations */
481     virtual void set_kinetostat_rhs(DENS_MAT & rhs, double dt);
482     /** adds in finite element rhs contributions */
483     virtual void add_to_rhs(FIELDS & rhs);
484 
485   private:
486 
487     // DO NOT define this
488     StressFluxGhost();
489 
490   };
491 
492   /**
493    *  @class  StressFluxFiltered
494    *  @brief  Enforces GLC on time filtered atomic forces based on FE stresses or accelerations
495    */
496 
497   //--------------------------------------------------------
498   //--------------------------------------------------------
499   //  Class StressFluxFiltered
500   //--------------------------------------------------------
501   //--------------------------------------------------------
502 
503   class StressFluxFiltered : public StressFlux {
504 
505   public:
506 
507     StressFluxFiltered(AtomicRegulator * kinetostat);
508 
~StressFluxFiltered()509     virtual ~StressFluxFiltered(){};
510 
511     /** adds in finite element rhs contributions */
512     virtual void add_to_rhs(FIELDS & rhs);
513 
514     /** get data for output */
515     virtual void output(OUTPUT_LIST & outputData);
516 
517   protected:
518 
519     // data
520     DENS_MAN & nodalAtomicVelocity_;
521 
522     // methods
523     /** sets up appropriate rhs for kinetostat equations */
524     virtual void set_kinetostat_rhs(DENS_MAT & rhs, double dt);
525 
526     /** apply forces to atoms */
527     virtual void apply_to_atoms(PerAtomQuantity<double> * quantity,
528                                 const DENS_MAT & lambdaAtom,
529                                 double dt);
530 
531   private:
532 
533     // DO NOT define this
534     StressFluxFiltered();
535 
536   };
537 
538   /**
539    *  @class  KinetostatGlcFs
540    *  @brief  Base class for implementation of kinetostat algorithms based on Gaussian least constraints (GLC)
541    *          when fractional step time integration is used
542    */
543 
544   class KinetostatGlcFs : public KinetostatShapeFunction {
545 
546   public:
547 
548     KinetostatGlcFs(AtomicRegulator *kinetostat,
549                     const std::string & regulatorPrefix = "");
550 
~KinetostatGlcFs()551     virtual ~KinetostatGlcFs(){};
552 
553     /** instantiate all needed data */
554     virtual void construct_transfers();
555 
556     /** pre-run initialization of method data */
557     virtual void initialize();
558 
559     /** applies thermostat to atoms in the predictor phase */
560     virtual void apply_pre_predictor(double dt);
561 
562     /** applies thermostat to atoms in the pre-corrector phase */
563     virtual void apply_pre_corrector(double dt);
564 
565     /** applies thermostat to atoms in the post-corrector phase */
566     virtual void apply_post_corrector(double dt);
567 
568     /** get data for output */
569     virtual void output(OUTPUT_LIST & outputData);
570 
571     /* flag for performing the full lambda prediction calculation */
572     bool full_prediction();
573 
574   protected:
575 
576     // methods
577     /** determine mapping from all nodes to those to which the kinetostat applies */
578     void compute_rhs_map();
579 
580     /** sets up appropriate rhs for kinetostat equations */
581     virtual void set_kinetostat_rhs(DENS_MAT & rhs,
582                                     double dt) = 0;
583 
584     /** apply forces to atoms */
585     virtual void apply_to_atoms(PerAtomQuantity<double> * atomicVelocity,
586                                 const DENS_MAN * nodalAtomicEnergy,
587                                 const DENS_MAT & lambdaForce,
588                                 DENS_MAT & nodalAtomicLambdaPower,
589                                 double dt);
590 
591     /** add contributions from kinetostat to FE energy */
592     virtual void add_to_momentum(const DENS_MAT & nodalLambdaForce,
593                                  DENS_MAT & deltaMomemtum,
594                                  double dt) = 0;
595 
596     /* sets up and solves the linear system for lambda */
597     virtual void compute_lambda(double dt);
598 
599     // member data
600     /** reference to AtC FE velocity */
601     DENS_MAN & velocity_;
602 
603     /** nodal atomic momentum */
604     DENS_MAN * nodalAtomicMomentum_;
605 
606     /** hack to determine if first timestep has been passed */
607     bool isFirstTimestep_;
608 
609     /** local version of velocity used as predicted final veloctiy */
610     PerAtomQuantity<double> * atomPredictedVelocities_;
611 
612     /** predicted nodal atomic momentum */
613     AtfShapeFunctionRestriction * nodalAtomicPredictedMomentum_;
614 
615     /** FE momentum change from kinetostat forces */
616     DENS_MAT deltaMomentum_;
617 
618     /** right-hand side data for thermostat equation */
619     DENS_MAT rhs_;
620 
621     /** fraction of timestep over which constraint is exactly enforced */
622     double dtFactor_;
623 
624     // workspace
625     DENS_MAT _lambdaForceOutput_; // force applied by lambda in output format
626     DENS_MAT _velocityDelta_; // change in velocity when lambda force is applied
627 
628   private:
629 
630     // DO NOT define this
631     KinetostatGlcFs();
632 
633   };
634 
635   /**
636    *  @class  KinetostatFlux
637    *  @brief  Implementation of kinetostat algorithms based on Gaussian least constraints (GLC)
638    *          which apply stresses when fractional step time integration is used
639    */
640 
641   class KinetostatFlux : public KinetostatGlcFs {
642 
643   public:
644 
645     KinetostatFlux(AtomicRegulator *kinetostat,
646                    const std::string & regulatorPrefix = "");
647 
~KinetostatFlux()648     virtual ~KinetostatFlux(){};
649 
650     /** instantiate all needed data */
651     virtual void construct_transfers();
652 
653     /** pre-run initialization of method data */
654     virtual void initialize();
655 
656     /** applies thermostat to atoms in the predictor phase */
657     virtual void apply_pre_predictor(double dt);
658 
659     /** applies thermostat to atoms in the post-corrector phase */
660     virtual void apply_post_corrector(double dt);
661 
662     /** enables resetting of filtered ghost force */
663     void reset_filtered_ghost_force(DENS_MAT & target);
664 
665   protected:
666 
667     // methods
668     /** sets up appropriate rhs for kinetostat equations */
669     virtual void set_kinetostat_rhs(DENS_MAT & rhs,
670                                     double dt);
671 
672     /** add contributions from kinetostat to FE energy */
673     virtual void add_to_momentum(const DENS_MAT & nodalLambdaForce,
674                                  DENS_MAT & deltaMomemtum,
675                                  double dt);
676 
677     /** sets up the transfer which is the set of nodes being regulated */
678     virtual void construct_regulated_nodes();
679 
680     // member data
681     /** reference to ATC sources coming from prescribed data, AtC coupling, and extrinsic coupling */
682     DENS_MAN & momentumSource_;
683 
684     /** force from ghost atoms restricted to nodes */
685     DENS_MAN * nodalGhostForce_;
686 
687     /** filtered nodal ghost force */
688     DENS_MAN * nodalGhostForceFiltered_;
689 
690   private:
691 
692     // DO NOT define this
693     KinetostatFlux();
694 
695   };
696 
697   /**
698    *  @class  KinetostatFluxGhost
699    *  @brief  Implements ghost-atom boundary flux and other loads for fractional-step based kinetostats
700    */
701 
702   class KinetostatFluxGhost : public KinetostatFlux {
703 
704   public:
705 
706     KinetostatFluxGhost(AtomicRegulator *kinetostat,
707                         const std::string & regulatorPrefix = "");
708 
~KinetostatFluxGhost()709     virtual ~KinetostatFluxGhost(){};
710 
711     /** instantiate all needed data */
712     virtual void construct_transfers();
713 
714     /** compute boundary flux */
715     virtual void compute_boundary_flux(FIELDS & fields);
716 
717   protected:
718 
719     /** sets up appropriate rhs for kinetostat equations */
720     virtual void set_kinetostat_rhs(DENS_MAT & rhs,
721                                     double dt);
722 
723     /** add contributions from kinetostat to FE energy */
724     virtual void add_to_momentum(const DENS_MAT & nodalLambdaForce,
725                                  DENS_MAT & deltaMomemtum,
726                                  double dt);
727 
728   private:
729 
730     // DO NOT define this
731     KinetostatFluxGhost();
732 
733   };
734 
735     /**
736    *  @class  KinetostatFixed
737    *  @brief  Implementation of kinetostat algorithms based on Gaussian least constraints (GLC)
738    *          which perform Hoover coupling when fractional step time integration is used
739    */
740 
741   class KinetostatFixed : public KinetostatGlcFs {
742 
743   public:
744 
745     KinetostatFixed(AtomicRegulator *kinetostat,
746                     const std::string & regulatorPrefix = "");
747 
~KinetostatFixed()748     virtual ~KinetostatFixed(){};
749 
750     /** instantiate all needed data */
751     virtual void construct_transfers();
752 
753     /** pre-run initialization of method data */
754     virtual void initialize();
755 
756     /** applies thermostat to atoms in the predictor phase */
757     virtual void apply_pre_predictor(double dt);
758 
759     /** applies thermostat to atoms in the pre-corrector phase */
760     virtual void apply_pre_corrector(double dt);
761 
762     /** applies thermostat to atoms in the post-corrector phase */
763     virtual void apply_post_corrector(double dt);
764 
765     /** compute boundary flux, requires thermostat input since it is part of the coupling scheme */
compute_boundary_flux(FIELDS &)766     virtual void compute_boundary_flux(FIELDS & /* fields */)
767       {boundaryFlux_[VELOCITY] = 0.;};
768 
769     /** determine if local shape function matrices are needed */
use_local_shape_functions()770     virtual bool use_local_shape_functions() const {return atomicRegulator_->use_localized_lambda();};
771 
772   protected:
773 
774     // methods
775     /** initialize data for tracking the change in nodal atomic velocity */
776     virtual void initialize_delta_nodal_atomic_momentum(double dt);
777 
778     /** compute the change in nodal atomic velocity */
779     virtual void compute_delta_nodal_atomic_momentum(double dt);
780 
781     /** sets up appropriate rhs for kinetostat equations */
782     virtual void set_kinetostat_rhs(DENS_MAT & rhs,
783                                     double dt);
784 
785     /** add contributions from kinetostat to FE energy */
786     virtual void add_to_momentum(const DENS_MAT & nodalLambdaForce,
787                                  DENS_MAT & deltaMomemtum,
788                                  double dt);
789 
790     /* sets up and solves the linear system for lambda */
791     virtual void compute_lambda(double dt);
792 
793     /** flag for halving the applied force to mitigate numerical errors */
794     bool halve_force();
795 
796     /** sets up the transfer which is the set of nodes being regulated */
797     virtual void construct_regulated_nodes();
798 
799     // member data
800     /** change in FE momentum over a timestep */
801     DENS_MAT deltaFeMomentum_;
802 
803     /** initial FE momentum used to compute change */
804     DENS_MAT initialFeMomentum_;
805 
806     /** change in restricted atomic FE momentum over a timestep */
807     DENS_MAT deltaNodalAtomicMomentum_;
808 
809     /** initial restricted atomic FE momentum used to compute change */
810     DENS_MAT initialNodalAtomicMomentum_;
811 
812     /** filtered nodal atomic momentum */
813     DENS_MAN nodalAtomicMomentumFiltered_;
814 
815     /** coefficient to account for effect of time filtering on rhs terms */
816     double filterCoefficient_;
817 
818     // workspace
819     DENS_MAT _tempNodalAtomicMomentumFiltered_; // stores filtered momentum change in atoms for persistence during predictor
820 
821   private:
822 
823     // DO NOT define this
824     KinetostatFixed();
825 
826   };
827 
828   /**
829    *  @class  KinetostatFluxFixed
830    *  @brief  Class for kinetostatting using the velocity matching constraint one one set of nodes and the flux matching constraint on another
831    */
832 
833   class KinetostatFluxFixed : public RegulatorMethod {
834 
835   public:
836 
837     KinetostatFluxFixed(AtomicRegulator * kinetostat,
838                         bool constructThermostats = true);
839 
840     virtual ~KinetostatFluxFixed();
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     /** applies thermostat to atoms in the post-corrector phase */
855     virtual void apply_post_corrector(double dt);
856 
857     /** get data for output */
858     virtual void output(OUTPUT_LIST & outputData);
859 
860     /** compute boundary flux, requires kinetostat input since it is part of the coupling scheme */
compute_boundary_flux(FIELDS & fields)861     virtual void compute_boundary_flux(FIELDS & fields)
862       {kinetostatBcs_->compute_boundary_flux(fields);};
863 
864   protected:
865 
866     // data
867     /** kinetostat for imposing the fluxes */
868     KinetostatFlux * kinetostatFlux_;
869 
870     /** kinetostat for imposing fixed nodes */
871     KinetostatFixed * kinetostatFixed_;
872 
873     /** pointer to whichever kinetostat should compute the flux, based on coupling method */
874     KinetostatGlcFs * kinetostatBcs_;
875 
876   private:
877 
878     // DO NOT define this
879     KinetostatFluxFixed();
880   };
881 
882 }
883 
884 #endif
885